Особенности сборки ядра
Ядро свободной POSIX-системы - это (почти) такая же программа, как и любая другая, распространяемая в исходных текстах. И потому оно также должно быть приведено в пригодное к употреблению состояние посредством сборки. Однако ядро все же - не пользовательское приложение и даже не системная утилита, и потому процесс сборки ядра имеет свою специфику.
Кроме того, ядро - это тот компонент, который и отличает в первую очередь одну POSIX-систему от другой - например, Linux от FreeBSD. Поэтому процесс сборки ядра для каждой операционки имеет свою специфику. Тогда как все сказанное выше касаемо сборки пакетов имеет силу (с очень незначительными оговорками) для любой POSIX-системы - причем даже не обязательно свободной: открытые приложения и утилиты для проприетарной Solaris или AIX в принципе собираются точно так же, как для Linux или какой-либо BSD.
Тем не менее, сборка ядра любой из рассматриваемых ОС включает те же стадии, что и сборка иных приложений - предварительное конфигурирование, собственно сборку и инсталляцию.
Конфигурирование ядра - это включение или выключение поддержки различных устройств (т.н. драйверов, хотя здесь это понятие существенно отличается от принятого в Windows), файловых систем, сетевых протоколов и т.д. Включение поддержки какой-либо опции подразумевает, что в ядро будет встроен код, обеспечивающий работу с неким устройством, файловой системой и проч. Кроме того, многие опции могут быть включены как модули. То есть соответствующий им код компилируется в бинарный вид, но непосредственно в ядро не встраивается, а подгружается в виде отдельной программы по мере необходимости - вручную, соответствующими командами, или автоматически.
Заметим, что, когда речь заходит о драйверах устройств, распространяемых отдельно от ядра операционной системы (например, производителями оборудования - некоторые из них признали ныне факт существования операционок, отличных от Microsoft Windows), имеются ввиду именно загружаемые модули ядра. Подобно другим программам, они могут существовать в виде исходников или в бинарном виде.
В первом случае их теоретически можно собрать для любой версии ядра (или, по крайней мере, для диапазона близких версий), разумеется, только данной ОС (драйверы для Linux, как можно догадаться, не будут работать во FreeBSD, и наоборот). Бинарные же, прекомпилированные, драйверы обычно жестко привязаны к версии ядра, хотя иногда могут как-то работать и при смене оной.
Процесс конфигурирования является наиболее ОС-специфичным во всей процедуре сборки ядра. Само собой разумеется, что ядра разных операционок имеют разные функции и, соответственно, разные опции конфигурирования - еще бы, ведь это все-таки разные программы. Но даже чисто внешне, на пользовательском уровне, процесс конфигурирования ядра Linux и, скажем, FreeBSD (или DragonFlyBSD) существенно отличается.
Во FreeBSD традиционным инструментом конфигурирования ядра выступает обычный текстовый редактор. С его помощью конфиг умолчального ядра (т.н. ядра GENERIC, устанавливаемого при инсталляции системы) приводится в соответствие с потребностями пользователя - одни опции отключаются, другие - включаются.
С отключаемыми опциями все понятно - они просто изымаются из умолчального конфига (путем установки символа комментария на соответствующих строках). А вот откуда взять опции недостающие? Они отыскиваются в некоем образцово-показательном конфигурационном файле. Во FreeBSD 4-й ветки (и это унаследовано в DragonFlyBSD) такой файл носит имя LINT (во FreeBSD для конфигов ядра принято употреблять символы верхнего регистра - этим подчеркивается величие сей программы) и был похож на настоящий - хотя и не работал (в смысле - скомпилировать из него работоспособное ядро было невозможно). В 5-й ветке на смену ему пришел файл NOTES - уже без претензий на всамделишность, это просто список всех теоретически доступных опций конфигурирования, снабженных достаточно подробными комментариями.
Специального включения/выключения модулей в конфигурационном файле ядра FreeBSD не предусмотрено - в качестве таковых по умолчанию собираются все выключенные опции, для которых модульная поддержка в принципе возможна (а она реализована еще не для всех опций).
Правда, это положение можно изменить правкой соответствующих конфигурационных файлов.
В первозданном (или каноническом - том, что скачивается с http://www.kernel.org) ядре Linux никакого умолчального конфигурационного файла не предусмотрено: он генерируется при первом же запуске штатного инструмента для ядерной настройки, базируемого все на той же утилите make - то есть представляющего собой одну из обычных ее целей.
Точнее, не одну - для изначального конфигурирования ядра предусмотрено ажно четыре цели: make config, make menuconfig, make xconfig и make gconfig. Все они делают одно дело - но каждая по своему.
Команда make config вызывает текстовый конфигуратор ядра, работающий в диалоговом режиме. То есть он требует ответа на множество вопросов, для которых предусмотрены варианты ответов - Yes и No, а для многих опций - еще и M (Module), который и обеспечивает подключение модульной поддержки (как и во FreeBSD, таковая возможна не для всех опций).
Использование make config представляется не очень удобным - в случае малейшей ошибки имеется только одна возможность для ее исправления - оборвать программу (например, через Control+C) и начать все заново. И вообще, этот метод конфигурирования считается устаревшим, и в ядрах ветки 2.6.X цель make config штатно не документирована. Хотя и может использоваться при желании - ее преимущество (по моему, несколько сомнительное) в том, что, в отличие от прочих средств конфигурирования, она не требует прав суперпользователя.
Команда make menuconfig, напротив, загружает весьма наглядный меню-ориентированный конфигуратор, богато оформленный псевдографикой. В каждом из подпунктов меню достаточно отметить нужные опции для их включения и, напротив, снять отметки для отключения. Опции, для которых реализована модульная поддержка, могут быть отмечены соответствующим образом.
Использование make menuconfig - пожалуй, наиболее употребимый (и удобный) способ конфигурирования ядра Linux. Нужно только помнить, что запуск соответствующей команды требует полномочий root'а: не то чтобы при этом происходит что-то особо брутальное, просто таковы атрибуты доступа к используемым целью menuconfig скриптам.
Команды make xconfig и make gconfig вызывают конфигураторы ядра, работающие в графическом режиме и, соответственно, могут быть запущены только в терминальном окне сеанса Иксов. В версиях ядра до 2.4.X включительно предусматривалась только первая из указанных целей, которая вызывала достаточно простую меню-ориентированную программу. В ядрах ветки 2.6.X цель make xconfig претерпела существенные изменения: теперь ею вызывается весьма "тяжелая", основанная на библиотеке Qt, программа, требующая также наличия в системе установленной среды KDE и пакета разработки kdevelop, что делает ее практически недоступной для многих пользователей. Ну а make gconfig влечет загрузку аналогичного по функциональности конфигуратора, но основанного на библиотеке Gtk. По причине стойкой нелюбви к последней я этим методом никогда не пользовался и ничего сказать о нем не могу.
Есть в Linux и еще несколько целей, обеспечивающих конфигурирование ядра. Так, командой make defconfig можно сгенерировать некий умолчальный ядерный конфиг - в нем будут включены именно те опции и модули, которые отмечены по умолчанию в меню make menuconfig.
При смене версии ядра можно прибегнуть к цели make oldconfig. Она восстановит конфигурацию ядра прежнего, запросив ответы только на вопросы, касающиеся вновь появившихся опций.
И, наконец, (почти) полный список доступных для конфигурирования ядра и его сборки целей можно получить посредством
$ make help
Собственно сборка ядра и в Linux, и в BSD-системах осуществляется командой make - возможно, с указанием неких конкретных целей. Останавливаться на их описании я сейчас не буду - тому придет свое время. Замечу только, что в Linux дополнительно нужно собрать и модули - командой
make modules
тогда как во FreeBSD это произойдет по умолчанию одновременно с компиляцией ядра.
В результате по завершении сборки у нас в подкаталогах дерева исходников ядра образуется собственно образ ядра - (почти) обычный исполняемый файл, - и набор скомпилированных модулей.
Это такие же объектные файлы, которые возникают на промежуточной стадии компиляции других программ. Так как к самостоятельному использованию они не предназначены, то и в линковке они не нуждаются.
Файл образа ядра во FreeBSD всегда носит имя kernel. В Linux же существует несколько видов образов, за которыми традициями закреплены фиксированные имена - типа vmlinuz, bzImage и еще несколько, о чем мы подробно поговорим тогда, когда до этого дойдет дело.
Как и компоненты любого прикладного пакета, образ ядра и сопровождающие его модули должны быть инсталлированы в должное место - в те подкаталоги, где система ожидает обнаружить их при загрузке. В Linux таких мест традиционно два - каталог /boot или, реже, корень файловой системы, тогда как для модулей предназначается каталог /lib/modules/X.Y.Z, где X.Y.Z - номер версии ядра (например, 2.6.7). Во FreeBSD, начиная с 5-й ветки, под ядро и модули отведен каталог /boot/kernel.В DragonFlyBSD (и остальных BSD-системах) ядро по прежнему размещается в корне файловой системы, модули же - в каталоге /modules.
Так вот, процесс инсталляции и сводится к тому, что файл образа ядра вместе с объектными модулями (а это ныне файлы вида *.ko - для отличия от обычных объектных файлов) копируется в надлежащие каталоги. Для этого предназначены специальные цели команды make. Во FreeBSD это make install или make kernelinstall. В Linux для установки модулей предназначена цель make modules_install, а само ядро может быть инсталлировано различными способами (в том числе - и просто ручным копированием).
В разделе о системных загрузчиках мы увидим, что в принципе ядро может быть размещено чуть ли не в любой части файловой системы. Нужно только позаботиться о том, чтобы программа, выступающая в данной ОС в качестве загрузчика, знала о его расположении. Однако нестандартное размещение ядра может создать некоторые проблемы и в любом случае потребует лишних телодвижений, так что лучше придерживаться традиционной схемы.