FreeBSF — Эксперименты с ядром

Эксперименты с ядром

Обычно первый шаг в оптимизации FreeBSD – конфигурирование ядра (kernel). Новичков в администрировании UNIX слово ядро может устрашить. Ведь ядро – это одна из тех скрытых частей системы, которые не предназначены для дилетантского вмешательства простых смертных. Действительно – в некоторых версиях UNIX непосредственные манипуляции с ядром немыслимы. Компания Microsoft вообще замалчивает факт наличия ядра в своих операционных системах, как бы ставя под сомнение наличие мозгов у пользователей.1 Хотя опытные пользователи могут получить досту п к ядру тем или иным способом, тем не менее такая возможность не предназначена для широких масс. Впрочем, в мире UNIX с открытым исходным кодом вмешательство в работу ядра считается приемлемым и даже ожидаемым способом улучшить производительность системы. Вероятно, если есть такая возможность, это наилучший способ и для настройки других систем.

Ядро FreeBSD можно настраивать динамически, или изменять на лету. При необходимости можно изменять большинство аспектов системной производительности. Далее будет обсуждаться интерфейс sysctl ядра и его применение для модификации рабочего ядра.

В то же время некоторые части ядра не подлежат изменению непосредственно при работе системы, а для настройки некоторых функций ядра необходима значительная реконфигурация. Например, существует возможность добавлять поддержку новых устройств или удалять поддержку устройств, которые не используются. Для этого лучше всего собрать собственное ядро, и далее будет показано, как это сделать.

Ядро FreeBSD имеет модульную архитектуру, что позволяет загружать и выгружать целые участки ядра, включая или выключая целые подсистемы по мере необходимости. Это очень удобно на данном этапе развития сменных устройств, таких как PC-карты и устройства USB. Загружаемые модули могут оказывать воздействие на производительность и поведение системы, а также на поддержку аппаратных устройств.

В заключение в этой главе будут рассмотрены основы отладки ядра, включая анализ порой устрашающих сообщений, а также поговорим о том, когда и как использовать альтернативные ядра.

Что такое ядро?

Ядро (kernel) имеет много разных определений. Значительная их часть абсолютно сбивает с толку. Некоторые определения являются технически корректными, но непонятными для начинающих пользователей, тогда как другие совершенно неправильные. Следующее определение не претендует на полноту, но оно понятно и удовлетворяет нашим целям: ядро – это интерфейс между аппаратным и программным обеспечением.

Ядро позволяет записывать данные на дисковые накопители и работать в сети. Когда программе требуется память, ядро выполняет все необходимые действия, организуя доступ к микросхемам физической памяти и выделяя ресурсы, необходимые для выполнения задания. Оно преобразует MP3 в поток нулей и единиц, которые понимает звуковая карта. Когда программа требует выделить ей квант процессорного времени, ядро обслуживает этот запрос и выделяет время. Проще говоря, ядро предоставляет интерфейсы программам, которым необходим доступ к аппаратным средствам.

Описывать работу ядра легко (по крайней мере, в этой упрощенной манере), но ее трудно выполнять. При взаимодействии с аппаратными средствами различные программы опираются на различные интерфейсы ядра, а аппаратные средства предоставляют свои ресурсы разными способами. Ядро должно справляться со всем этим. Например, ядро поддерживает несколько десятков типов сетевых карт, причем карты каждого типа предъявляют свои требования, которые ядро должно удовлетворить. Если ядро окажется не в состоянии обслуживать сетевую карту, система не сможет подключиться к сети. Программы запрашивают память различными способами, и если программа запрашивает память способом, который не поддерживается ядром, возникает затруднение. При загрузке ядро получает сведения об аппаратных средствах, и их дальнейшая работа определяется полученными сведениями. Значит, этим процессом надо управлять. Некоторые устройства идентифицируют себя довольно дружественным, по отношению к ядру, способом, а другие накрепко блокируются при попытке узнать, что это за устройства и для чего они предназначены.

Фактически, ядро и его модули – это файлы в каталоге /boot/kernel. Файлы, находящиеся за пределами этого каталога, не являются частями ядра; эти файлы и программы называются пользовательским пространством (userland), то есть они предназначены для пользователей, даже если они во время работы обращаются к ядру.

Поскольку ядро – это всего лишь набор файлов, вы можете создавать свои, альтернативные ядра, предназначенные для особых случаев. В системе, где была выполнена сборка собственного ядра, можно обнаружить каталог /boot/kernel.old, где находится ядро, работавшее до того, как была выполнена установка текущего ядра. Я предпочитаю хранить ядро, установленное вместе с системой в каталоге /boot/kernel.install. Вы также можете создавать свои собственные ядра. Команда FreeBSD стремится к тому, чтобы сделать настройку и установку ядра как можно проще. Самый простой способ изменить ядро – это использовать интерфейс sysctl.

sysctl

Программа sysctl(8) позволяет взглянуть на параметры ядра и в некоторых случаях установить их значения. Запутаем дело: иногда эти параметры тоже называются sysctls. Sysctl – это мощный инструмент, поскольку во многих случаях он позволяет увеличивать производительность без повторной сборки ядра или переконфигурирования приложения. К сожалению, это палка о двух концах – таким образом можно нарушить работу программ и сделать пользователей очень несчастными.

Все операции над параметрами настройки ядра (sysctls) выполняются с помощью команды sysctl(8). По ходу изложения материала я буду обращать внимание на ту или иную операцию sysctl, которая изменяет поведение системы, но сначала эти операции необходимо понять. Прежде чем взяться за sysctls, выясним, какие из них доступны в системе. Следующая команда сохранит список операций в файле, который можно легко изучить:

# sysctl A > sysctl.out

После выполнения этой команды файл sysctl.out будет содержать сотни параметров настройки ядра и их значений. Большая их часть пока неясна, но некоторые понять нетрудно:

kern.hostname: humvee.blackhelicopters.org

Этот параметр sysctl, называемый kern.hostname, имеет значение humvee.blackhelicopters.org. Система, на которой я запустил эту команду, называется humvee.blackhelicopters.org. По названию этого параметра ядра нетрудно догадаться, что он хранит имя компьютера. Если бы все было так просто…

kern.ipc.msqids: Format: Length:3520

Dump:0xe903e903e903e903c0010100168f7542…

 

Я понятия не имею, какую роль играет переменная kern.ipc.msqids, и еще меньше понимаю смысл ее значения. Все же, если у меня возникают трудности, я могу получить нужную информацию, обратившись за помощью к поставщику системы или в почтовую рассылку.

Организация sysctl

Параметры настройки ядра организованы по древовидной схеме, которая называется базой управляющей информации (Management Information Base, MIB). В ней есть несколько основных категорий, таких как net (network – сеть), vm (virtual memory – виртуальная память) и kern (kernel – ядро). В табл. 5.1 перечислены корневые элементы дерева MIB sysctl, присутствующие в системе, работающей на базе ядра GENERIC.

Таблица 5.1. Корни дерева sysctl MIB

Sysctl Назначение

kern Основные функции ядра

vm Подсистема виртуальной памяти

vfs Файловые системы

net Сетевые функции

debug Отладочная информация

hw Информация об аппаратных средствах

user Информация об интерфейсах пространства пользователя

p1003_1b Параметры, управляющие характеристиками POSIXa

compat Совместимость ядра с программным обеспечением других операционных систем (глава 12)

security Параметры обеспечения безопасности dev Информация драйверов устройств

POSIX – это международный стандарт, описывающий характеристики и возможности UNIX-подобных операционных систем. К сожалению, стандарт POSIX сильно изменился за последние годы, причем эти изменения иногда настолько непоследовательны, что системы, соответствующие требованиям одной версии POSIX, могут оказаться несовместимы с другими версиями стандарта. Если вы хорошо знакомы со стандартом POSIX, вы наверняка знаете, что это за различия. С помощью параметров sysctl вы сможете точно узнать о поведении FreeBSD и какой версии стандарта она соответствует.

Каждая категория, в свою очередь, подразделяется на подгруппы; например, категория net, охватывающая все сетевые sysctls, разделена на категории IP, ICMP, TCP и UDP. Термины sysctl MIB и sysctl часто употребляются попеременно. Концепция, лежащая в основе базы управляющей информации (MIB), используется и в других частях операционной системы, в чем вы сможете убедиться в главе 20 и на протяжении всей своей карьеры. Термины sysctl MIB и sysctl часто употребляются попеременно. Уникальные имена переменных создаются из комбинации названия родительской категории и всех вложенных подкатегорий, например:

kern.maxfilesperproc: 11095

kern.maxprocperuid: 5547

kern.ipc.maxsockbuf: 262144

kern.ipc.sockbuf_waste_factor: 8

kern.ipc.somaxconn: 128

Здесь представлены пять параметров sysctl, извлеченные из категории kern. Первые два входят непосредственно в категорию kern, и с другими значениями их связывает лишь тот факт, что все они имеют отношение к ядру. Имена остальных трех параметров начинаются с kern.ipc – они являются частью раздела IPC (inter-process communication – взаимодействие между процессами). Если продолжить рассмотрение сохраненного ранее файла со списком параметров sysctl, можно заметить, что ветвление дерева sysctls может продолжаться на нескольких уровнях.

Значения параметров sysctl

Каждый MIB имеет значение, которое связано с неким буфером, настройками или особенностями, используемыми ядром. Изменение этого значения повлечет за собой изменение в характере работы ядра. Например, некоторые параметры настройки ядра управляют выделением памяти для каждого сетевого соединения. Если сетевая производительность низка, можно увеличить объем системных ресурсов, резервируемых для сетевых соединений.

Каждый параметр sysctl может представлять собой строку (string), целое число (integer), двоичное значение (binary value) либо неясный код (opaque). String – это текст свободного формата с произвольной длиной; integer – обыкновенное целое число; binary value – либо 0 (off), либо 1 (on); значение opaque представлено в машинном коде, который могут интерпретировать только специальные программы. Многие параметры настройки ядра недостаточно документированы. Нет отдельного документа, в котором перечислены все имеющиеся базы управляющей информации (sysctl MIB) и их назначение. Но описание каждого параметра присутствует на странице руководства к соответствующей функции, а иногда– только в исходных текстах. Например, исходная документация для MIB kern.securelevel (более подробно рассматривается в главе 7) представлена в init(8). Хотя за последние несколько лет объем документации по sysctl существенно вырос, тем не менее многие параметры по-прежнему вообще не имеют документации. В приложении A приведен список распространенных параметров настройки ядра и описано их назначение.

К счастью, некоторые параметры очевидны. Например, как будет говориться ниже, в этой же главе, следующий параметр имеет большое значение для тех, кто часто загружает систему с различными ядрами:

kern.bootfile: /boot/kernel/kernel

 

Если проводится отладка и последовательная загрузка с различных ядер, можно легко забыть, какое ядро было загружено (в действительности это происходит даже со мной), поэтому дополнительное напоминание будет совсем нелишним.

Просмотр параметров sysctl

Чтобы увидеть поддерево MIB, доступных в отдельном поддереве MIB, можно воспользоваться командой sysctl, передав имя поддерева, которое следует вывести. Например, чтобы увидеть все параметры в дереве, таком как kern, введите такую команду:

# sysctl kern
kern.ostype: FreeBSD kern.osrelease: 7.0-CURRENT-SNAP010 kern.osrevision: 199506

Этот список может быть длинным. Он может пригодиться, когда необходимо выяснить, какие параметры sysctl представлены в ядре. Чтобы получить только значение отдельного параметра настройки ядра, задайте имя MIB как аргумент:

# sysctl kern.securelevel kern.securelevel: -1

В этом случае kern.securelevel имеет целочисленное значение –1. Смысл этого значения обсуждается в главе 7.

Чтобы получить хоть какое-то представление о назначении того или иного параметра sysctl, можно использовать ключ –d вместе с полным именем MIB. В результате будет выведено краткое описание параметра:

# sysctl d kern.maxfilesperproc
kern.maxfilesperproc: Maximum files allowed open per process

Это краткое описание сообщает, что данный параметр sysctl управляет именно тем, о чем можно было бы догадаться из его имени. Но это самый простой случай, в других, более сложных случаях, бывает сложно строить какие-либо предположения только на основе имени параметра.

Изменение параметров sysctl

Некоторые параметры sysctl предназначены только для чтения. Рассмотрим MIB-дерево hw:

hw.model: AMD Athlon(tm) 64 X2 Dual Core Processor 4200+

 

Разработчики FreeBSD еще не до конца разработали технологию переноса системы с AMD на аппаратные средства sparc64 с помощью программных настроек, поэтому данный параметр доступен только для чтения и его изменение может привести лишь к неработоспособности системы. Вот почему во FreeBSD такие параметры MIB доступны только для чтения. Попытки изменить их ничего не нарушат, однако будет выдано предупреждение о том, что сделать это нельзя. Но есть MIB, значения которых изменять можно. Рассмотрим следующий MIB:

vfs.usermount: 0

 

Его значение определяет, могут ли пользователи монтировать сменные носители, такие как CD или дискету. Изменение этого параметра не требует внесения обширных изменений в ядро или в аппаратное окружение, он всего лишь разрешает или запрещает функцию в ядре. Чтобы изменить значение параметра, следует вызвать команду sysctl(8), передать ей имя параметра, знак «равно» (=) и желаемое значение:

# sysctl vfs.usermount=1 vfs.usermount: 0 -> 1

Команда sysctl(8) возвращает сообщение, в котором показаны предыдущее и новое значения. После этого параметр sysctl будет изменен. Параметры sysctl, которые подстраиваются «на лету», называются sysctl, настраиваемые на этапе выполнения (runtime tunable sysctl).

Автоматическая настройка параметров sysctl

Когда будут выполнены все необходимые настройки параметров ядра, было бы желательно, чтобы они автоматически устанавливались после перезагрузки. Для этих целей используется файл /etc/sysctl.conf. Просто перечислите в этом файле все желаемые параметры с необходимыми значениями. Например, чтобы установить тот же самый параметр vfs.usermount на этапе загрузки, достаточно добавить в /etc/sysctl.conf следующую строку:

vfs.usermount=1

 

Параметры sysctl, устанавливаемые на этапе загрузки

Некоторые этапы конфигурирования ядра должны предшествовать загрузке системы. Можно найти множество примеров параметров, значения которых должны определяться на этапе загрузки. Часто эти параметры связаны с низкоуровневой настройкой аппаратных устройств. Например, во время первоначального опроса ядром жесткого диска IDE драйвер устройства определяет, следует ли использовать DMA, PIO, кэширование записи или какие-либо другие особенности, характерные для жестких дисков. Это решение должно приниматься при обнаружении устройства, на этапе начальной загрузки, после чего решение изменить нельзя. Эти значения можно установить с помощью  системного загрузчика (system loader), определив необходимые настройки в файле /boot/loader.conf, как уже говорилось в главе 3.

Настройки в loader.conf, как и в sysctl.conf, при неумелом использовании могут доставить компьютеру неприятности. Но нет причин для расстройства, потому что эти значения легко можно сбросить.

 

Слишком много настроек?

Не путайте между собой параметры sysctl, значения которых могут устанавливаться только на этапе загрузки, параметры, которые могут изменяться в процессе работы системы, и параметры, которые могут изменяться в процессе работы, но настроены для автоматической установки на этапе загрузки. Запомните, что настройки, выполняемые только на этапе загрузки, связаны с низкоуровневыми функциями ядра, тогда как настройки, позволяющие изменять свои значения «на лету», – с высокоуровневыми. Автоматическая настройка параметров sysctl во время загрузки – это просто пример экономии вашего времени; принадлежность параметров к той или иной категории не изменяет-

Выдача указаний драйверам устройств

Многие драйверы устройств требуют, чтобы флаги sysctl были установлены во время начальной загрузки. Узнать о них можно из страниц руководства, из этой книги и из другой документации. Несмотря на то, что эти параметры отсутствуют в файле по умолчанию loader.conf, тем не менее их можно добавлять в локальный loader.conf, чтобы автоматически задавать необходимые значения во время начальной загрузки. Например, чтобы отключить DMA для устройств ATAPI (которые будут рассматриваться в главе 8), достаточно просто поместить требуемое значение параметра sysctl в файл loader.conf:

hw.ata.atapi_dma=»0″

 

Ядро установит этот флаг во время загрузки, и тем самым будет обеспечено желаемое поведение драйвера устройства.

Дополнительно многие устаревшие аппаратные устройства требуют, чтобы ядро обращалось к ним по сигналу прерывания, с четко определенным номером IRQ и по определенным адресам памяти. Если вам достаточно лет, вы должны помнить дискеты для «настройки устройств» и специальные разъемы для подключения плат расширения шин, вы знаете, о чем я говорю, и, возможно, одна из таких систем даже сейчас валяется у вас на заднем дворе. (Если же вы слишком молоды, купите выпить для одного из нас, старикашек, и слушайте1 наши рассказы, наполненные ужасами.) Можно указать системе FreeBSD на необходимость опробовать все номера IRQ или указанные адреса памяти для работы с этими устройствами, что очень удобно, если имеется карта с известными параметрами настройки, но дискета с ними давно уже превратилась в прах. Загляните в файл /boot/device.hints, где можно увидеть массу записей, таких как показано ниже:

hint.ed.0.disabled=»1″  hint.ed.0.port=»0x280″
hint.ed.0.irq=»10″
hint.ed.0.maddr=»0xd8000″

Данные записи – это указания для драйвера ed . Запись предназначена для драйвера ed с номером 0 . Ключевое слово disabled  означает, что FreeBSD не будет выполнять проверку этого устройств автоматически, во время загрузки. Если будет найдена другая карта ed, ей может быть присвоен номер устройства 0. Если это устройство будет активировано, FreeBSD попробует обратиться к нему через порт с номером 0x280 , по номеру IRQ 10  и по адресу памяти 0xd8000 , и если карта будет обнаружена по указанным адресам, она получит имя устройства ed0. Конечно, если карта не поддерживается драйвером сетевых карт ed(4), у вас появятся другие проблемы!

Команда sysctl(8) дает вам власть выполнять настройку ядра, но настройка – это только начало пути. Следующий шаг – управление модулями ядра.

Тестирование настроек, выполняемых во время загрузки

Все эти указания драйверам и настройки, выполняемые во время загрузки, можно производить в интерактивном режиме, в командной строке загрузчика, о которой рассказывалось в главе 3. Вы можете протестировать настройки без редактирования файла loader.conf, отыскать правильное значение и только после этого сохранить его в файле.

Модули ядра

Как уже говорилось, модули ядра – это его компоненты, которые можно запускать (или загружать) и выгружать при необходимости. Модули ядра могут загружаться при подключении устройств и выгружаться при их отключении. Это позволяет экономить системную память и повышает гибкость системы.

Само ядро по умолчанию хранится в виде файла /boot/kernel/kernel, модули ядра также хранятся в виде файлов в каталоге /boot/kernel. Заглянув в этот каталог, можно увидеть сотни файлов модулей ядра. Имена файлов всех модулей ядра имеют расширение .ko. Обычно файлы модулей ядра получают имена, соответствующие их функциональности. Например, в файле /boot/kernel/joy.ko находится драйвер джойстика (от английского «joy»), описание которого находится в странице руководства joy(4). Этот драйвер делает джойстик видимым для системы в виде устройства joy0.

Просмотр списка загруженных модулей

В главе 3 было показано, как получить список загруженных модулей перед загрузкой, но этот метод не годится, после того как система загрузится. Получить список загруженных в настоящий момент модулей ядра можно с помощью команды kldstat(8).

# kldstat

Id Refs Address Size Name
1 15 0xc0400000 6a978c kernel
2 1 0xc0aaa000 6228 snd_via8233.ko  3 2 0xc0ab1000 23898 sound.ko

На этом ноутбуке загружено три модуля ядра. Первый – это ядро , далее идут драйвер звуковой карты  и звуковая подсистема . (Это совершенно неудивительно, так как речь идет о ноутбуке.) Каждый модуль содержит один или более подмодулей, которые можно увидеть с помощью команды kldstat –v, но само ядро содержит несколько сотен подмодулей, поэтому будьте готовы получить очень длинный список.

Загрузка и выгрузка модулей

Загрузка и выгрузка модулей ядра производится с помощью команд kldload(8) и kldunload(8). Например, обычно мой ноутбук подключается к сети посредством проводного соединения Ethernet. При беспроводном подключении мне необходимо загрузить модуль ядра wlan_wep.ko, который использует WEP-шифрование. Для этого я пользуюсь командой kldload, которой передаю имя файла модуля ядра с требуемой функциональностью:

# kldload /boot/kernel/wlan_wep.ko

Как только беспроводное подключение станет ненужным, я выгружаю модуль.1 Для этого требуется указывать не имя файла, а имя модуля, в том виде, как его отображает команда kldstat:

# kldunload wlan_wep.ko
Если бы все возможные функции компилировались непосредственно в ядро, оно имело бы очень большой размер. Модульная архитектура позволяет уменьшить ядро, сделать его более эффективным, а редко используемые функции загружать только в случае необходимости.

Команды kldload(8) и kldunload(8) не требуют указания полного пути к модулю ядра, точно так же они не требуют указания расширения файла .ko. Если вы помните точное имя файла модуля ядра, можно использовать примерно такие команды:

# kldload wlan_wep
# kldunload wlan_wep

Лично я, со своим слабеньким мозгом, полагаюсь на функцию автоматического дополнения, присутствующую в командной оболочке, которая напоминает мне полные и правильные имена модулей.

Автоматическая загрузка модулей ядра

Для автоматической загрузки модуля надо добавить его в файл /boot/ loader.conf. Файл по умолчанию loader.conf содержит множество примеров загрузки модулей ядра, в которых используется один и тот же синтаксис. Нужно взять имя модуля ядра, убрать расширение файла .ko и добавить к нему строку _load=»YES». Например, чтобы автоматически загрузить модуль /boot/kernel/procfs.ko, в файл loader.conf нужно добавить такую строку:

procfs_load=»YES»

 

Самое сложное во всем этом – узнать точное имя модуля, который требуется загрузить. Пользоваться драйверами устройств проще простого – если ядро не поддерживает новую сетевую карту или устройство SCSI, тогда вместо перенастройки ядра можно просто загрузить модуль драйвера. В этом случае нужно выяснить, какой драйвер поддерживает подключенное устройство, и здесь вам помогут страницы руководства и поисковая система Google. Везде в этой книге я буду упоминать модули ядра, которые помогут решать те или иные проблемы.

Впрочем, подождите минутку – зачем FreeBSD вынуждать загружать драйверы устройств, если она сама определяет их во время загрузки? Отличный вопрос! Дело в том, что вы можете собрать свое собственное ядро и удалить поддержку неиспользуемого устройства. Вы до сих пор не знаете, как собрать свое собственное ядро? Сейчас мы исправим этот недостаток.

Сборка собственного ядра

В какой-то момент становится ясно, что существующее ядро уже не удается подгонять под стоящие задачи только с помощью модулей и sysctl. Единственное решение в этом случае – собрать собственное ядро. Не стоит волноваться – этот процесс очень прост, поскольку в данном случае речь идет не о написании программного кода, а всего лишь о редактировании текстового файла и о запуске пары команд. Если неукоснительно следовать инструкциям, то сборка ядра становится достаточно безопасным процессом. Отказ от следования рекомендациям – это как езда на автомобиле по встречной полосе. (В центре, в час пик.)

Ядро, поставляемое по умолчанию, называется GENERIC. Это ядро предназначено для работы с широким спектром аппаратных средств, но оно не обязательно будет работать хорошо или оптимально. GENERIC прекрасно запускается на системах, выпущенных в последнее десятилетие или около того. Однако новейшие устройства обладают возможностями оптимизации своей работы, которые не поддерживаются ядром GENERIC, ориентированном на «наименьший общий знаменатель». Даже в этом случае оно прекрасно подходит для повседневного использования. При настройке ядра можно подключить необходимые функции оптимизации, добавить поддержку новых устройств, удалить поддержку устройств, которые не используются, или активировать какие-либо новые возможности.

Процесс сборки ядра нередко считают неким таинственным ритуалом, но сообщество поддержки FreeBSD не будет долго думать над вопросом – собирать или не собирать новое ядро, чтобы включить или исключить какую-либо особенность. Не надо думать, что пересборка ядра способна решить любую проблему; тем не менее этим умением должен обладать любой системный администратор.

Подготовка

Для сборки ядра необходим его исходный код. Если читатель последовал совету, данному в главе 2, то все уже готово. Если нет, надо вернуться в программу установки и загрузить исходный код ядра или перейти к главе 13 и использовать команду cvsup(8). Если неизвестно, инсталлирован ли исходный код ядра, поищите каталог /sys. Если он существует, и в нем имеются файлы и подкаталоги, значит, искомый код у вас есть.

Перед созданием нового ядра выясните, какие аппаратные средства присутствуют в системе. Порой это нелегко, поскольку торговая марка на компоненте необязательно имеет хоть какое-то отношение к возможностям и отличительным чертам устройства. Многие компании занимаются ребрэндингом универсальных компонентов – я помню одного производителя, который выпускал четыре разных типа сетевых карт с одним и тем же названием и не утруждал себя необходимостью указывать номер версии на первых трех из них. Единственный способ отличить их состоял в том, чтобы пробовать использовать разные драйверы устройств, пока не будет найден тот, который работает. Похожим образом многие компании производят сетевые карты, совместимые с NE2000. Даже если на коробке написано другое название, данное производителем, микросхемы чипа могут сообщать о себе как об устройствах NE2000. К счастью, некоторые производители используют стандартную архитектуру для своих устройств и драйверов. Так, вы всегда можете быть уверены, что сетевые карты компании Intel будут распознаваться драйверами устройств Intel.

Чтобы узнать, какие аппаратные средства обнаружила система FreeBSD, лучше всего обратиться к /var/run/dmesg.boot, о чем уже говорилось в главе 3. Каждая запись в этом файле представляет либо аппаратное устройство, либо программную особенность ядра. Приступая к сборке нового ядра, всегда держите под рукой файл dmesg.boot.

Шины и подключения

Каждое устройство в компьютере подключается к некоторому другому устройству. Если внимательно просмотреть файл dmesg.boot, можно увидеть целые цепочки устройств, подключенных друг к другу. Ниже приводится несколько сообщений из файла, в демонстрационных целях отредактированных:

acpi0: <PTLTD RSDT> on motherboard
acpi_ec0: <Embedded Controller: GPE 0xb> port 0x62,0x66 on acpi0  cpu0: <ACPI CPU> on acpi0

cpu1: <ACPI CPU> on acpi0
pcib0: <ACPI Host-PCI bridge> port 0xcf8-0xcff on acpi0  pci0: <ACPI PCI bus> on àpcib0

Первое устройство в данной системе – это acpi0 . Скорее всего, вы не знаете, что это за устройство, но вы всегда можете воспользоваться командой man acpi, чтобы ликвидировать этот недостаток. (Или прочитать оставшуюся часть главы.) Следующее устройство в системе – acpi_ec , и оно подключено к устройству acpi0 . Микропроцессоры  также подключены к acpi0, как и мост PCI . Наконец, имеется первая шина PCI, pci0 , подключенная к мосту PCI, а не к acpi0. Обычно устройства PCI подключаются к иерархии шин PCI, которая в свою очередь подключается к мосту PCI, чтобы иметь возможность обмениваться данными с остальными компонентами компьютера. Можно было бы ознакомиться со всем содержимым файла dmesg.boot и нарисовать дерево подключения всех устройств в системе – хотя это и не является необходимым условием, тем не менее знание схемы включения устройств увеличивает вероятность успешной сборки нового ядра.

Если у вас что-то вызывает сомнения, воспользуйтесь утилитой pciconf(8), чтобы увидеть, что в действительности имеется в вашей системе. Команда pciconf –lv перечислит все подключенные устройства PCI, имеющиеся в системе, независимо от того, были они обнаружены ядром или нет.

Сохранение рабочего ядра

Из-за плохого ядра система может перестать загружаться, поэтому абсолютно необходимо всегда иметь под рукой хорошее ядро. В процессе установки нового ядра старое сохраняется на всякий случай в виде файла /boot/kernel.old. Это замечательно – иметь возможность вернуться к рабочему ядру в случае ошибки, но я рекомендую двинуться дальше.

Если хорошего надежного ядра нет, события могут развиваться так. При сборке нового ядра вы вдруг обнаруживаете, что допустили незначительную оплошность, и решаете устранить ее, еще раз пересобрав ядро. В этом случае заново собранное ядро становится текущим, а предыдущее (с изъяном) в свою очередь заменит старое, рабочее ядро, которое исчезнет. Когда обнаружится, что новое ядро содержит ту же самую или даже более серьезную ошибку, останется только сожалеть о том, что надежное ядро утеряно.

Обычное место для хранения хорошо зарекомендовавшего себя ядра – /boot/kernel.good. Перед настройкой ядра сохраните надежное работающее ядро:

# cp Rp /boot/kernel /boot/kernel.good

Не бойтесь хранить несколько ядер. Дисковое пространство в наше время очень дешево. Некоторые администраторы даже размещают ядра в каталогах, названных по дате ядра. Благодаря этому они всегда могут вернуться к более ранней версии ядра. Кроме того, многие хранят копию ядра GENERIC в виде файла /boot/kernel.GENERIC для нужд тестирования и отладки. Ядер слишком много бывает лишь в том случае, если они совершенно заполнили корневой раздел.

Формат конфигурационного файла

Ядро FreeBSD конфигурируется через текстовый файл. Для конфигурирования ядра отсутствуют какие-либо графические утилиты, управляемые системой меню, – процесс конфигурирования ядра не изменился со времен 4.4 BSD. Если вы чувствуете дискомфорт при работе с текстовыми конфигурационными файлами, тогда сборка нового ядра – не для вас.

Каждая конфигурационная запись располагается на отдельной строке. Каждая запись начинается с идентификационной метки, указывающей тип записи, за которой следует описание функции. Среди записей можно встретить множество комментариев, которые начинаются с символа решетки (#), как в следующей записи, соответствующей поддержке файловой системе FFS:

options FFS # Berkeley Fast Filesystem

 

В каждом конфигурационном файле ядра присутствуют записи пяти типов: cpu, ident, makeoptions, options и devices. Наличие или отсутствие этих записей определяет наличие поддержки аппаратных устройств или функциональных возможностей.

cpu Данная метка указывает, какие типы процессоров поддерживаются ядром. Конфигурационный файл ядра, предназначенного для устаревших персональных компьютеров, включал в себя несколько записей с указанием типа процессора, такие как 486 (I486_CPU), Pentium (I586_CPU) и для серии процессоров от Pentium Pro до современных Pentium 4 (I686_CPU). Конфигурация ядра для аппаратной платформы amd64/EM64T включает в себя единственную запись с указанием типа процессора. Конфигурация ядра может включать несколько типов процессоров при условии, что они принадлежат одной и той же архитектуре, – можно собрать ядро, которое будет работать и на процессорах 486, и на процессорах Pentium, но невозможно получить ядро, которое могло бы работать как на Intel-совместимых процессорах, так и на процессорах Sparc.

ident Строка, начинающаяся с метки ident, содержит имя ядра. Именно таким образом ядро GENERIC получает свое имя. Это может быть любая произвольная строка.

makeoptions Данная строка содержит инструкции для программного обеспечения, выполняющего сборку ядра. Наиболее распространенный параметр – DEBUG=–g, который сообщает компилятору о необходимости включения в ядро отладочной информации. Отладочная информация помогает разработчикам в разрешении возникающих проблем.

options Записи этого типа описывают функции ядра, которые непосредственно не связаны с аппаратным обеспечением. Сюда входят файловые системы, сетевые протоколы и отладчики, встроенные в ядро.

devices Записи этого типа описывают устройства или драйверы устройств, они содержат инструкции, которые описывают, как ядро должно взаимодействовать с определенными устройствами. Если вам необходимо, чтобы система осуществляла поддержку некоторого аппаратного обеспечения, ядро должно включать драйвер этого аппаратного устройства. Некоторые записи этого типа соответствуют так называемым псевдоустройствам, которые в действительности не являются аппаратными устройствами, а обеспечивают поддержку целых категорий аппаратных устройств, таких как сетевые карты, генераторы случайных чисел или электронные диски. Здесь вполне может появиться вопрос – чем псевдоустройства отличаются от записей типа options. Дело в том, что псевдоустройства тем или иным способом отображаются в системе как устройства, тогда как функциональные возможности типа options не имеют отличительных особенностей, присущих устройствам. Например, петлевое (loopback) псевдоустройство – это сетевой интерфейс, который позволяет подключаться только к локальному компьютеру. В данном случае отсутствует какое-либо аппаратное обеспечение, тем не менее программы могут подключаться через петлевой интерфейс и обмениваться данными с программами, исполняемыми на том же самом компьютере.

Конфигурационные файлы

К счастью, обычно не требуется создавать конфигурационные файлы на пустом месте – вместо этого достаточно скопировать существующий файл и отредактировать его. Начнем с ядра GENERIC, предназначенного для вашей аппаратной архитектуры. Найти этот конфигурационный файл можно в каталоге /sys/<arch>/conf – например, конфигурационные файлы ядра для архитектуры i386 находятся в каталоге /sys/i386/ conf, для архитектуры amd64 – в каталоге /sys/amd64/conf и т. д. В каталоге находятся несколько файлов, из которых наиболее важными являются DEFAULTS, GENERIC, GENERIC.hints, MAC и NOTES:

DEFAULTS Это список параметров и устройств, поддержка которых включена по умолчанию для данной архитектуры. Наличие этого файла совершенно не означает, что можно скомпилировать и запустить ядро DEFAULTS, – это лишь отправная точка, позволяющая собрать ядро с минимальными возможностями.

GENERIC Этот файл содержит конфигурацию стандартного ядра. В нем присутствуют настройки, обеспечивающие поддержку стандартного аппаратного окружения, необходимую для запуска ядра на данной архитектуре – этот конфигурационный файл используется инсталлятором системы.

GENERIC.hints Это файл с указаниями, который впоследствии устанавливается как /boot/device.hints. В данном файле содержится конфигурационная информация, необходимая для настройки устаревших аппаратных устройств.

MAC Этот конфигурационный файл ядра обеспечивает поддержку обязательного контроля доступа (Mandatory Access Controls) – системы многоуровневого управления доступом, используемой в средах с высокой степенью защиты. Этот конфигурационный файл требуется только в случае использования MAC.

NOTES Это комплексная конфигурация ядра для заданной аппаратной архитектуры. В файл NOTES включены все особенности, характерные для той или иной платформы. Платформонезависимые особенности можно найти в файле /usr/src/sys/conf/NOTES.

Не редактируйте эти файлы непосредственно в каталоге с конфигурациями. Вместо этого скопируйте файл GENERIC в файл, содержащий имя компьютера, и редактируйте копию. Например, мой ноутбук имеет имя humvee.blackhelicopters.org: я мог бы скопировать файл GENERIC в файл HUMVEE и открыть файл HUMVEE в своем любимом текстовом редакторе. Ниже приводится отрывок из конфигурационного файла, точнее, та его часть, которая описывает устройства ATA:

# ATA and ATAPI devices

device          ata

device          atadisk        # ATA disk drives

device          ataraid        # ATA RAID drives

 

device           atapicd

device           atapifd

device           atapist

# ATAPI CDROM drives

# ATAPI floppy drives

# ATAPI tape drives

options ATA_STATIC_ID  # Static device numbering

C символа «решетка» (#) начинаются комментарии – все, что находится после этого символа и до конца строки, игнорируется. Этот символ отделяет текст, предназначенный для компьютера, от текста, предназначенного для человека. Например, первая строка в этом фрагменте сообщает, что следующие записи отвечают за настройку устройств ATA и ATAPI. В других строках присутствуют комментарии, начинающиеся в середине строк, которые информируют о назначении каждой отдельной записи.

Сравните эти записи с парой записей в /var/run/dmesg.boot, которые соответствуют устройствам ATA:

ata1: <ATA channel 1> on atapci1

acd0: DVDR <PIONEER DVD-RW DVR-K16/1.33> at ata1-master UDMA33

 

Конфигурационный файл ядра описывает шину ATA, устройство ata, и в файле dmesg.boot присутствует упоминание о канале ATA – ata1. Привод DVD-RW подключен к ata1. Без наличия устройства ata в конфигурационном файле ядро не смогло бы определить наличие шины ATA. Даже если бы системе удалось определить наличие устройства DVD, она все равно не знала бы, как производить обмен данными с ним. Ваша конфигурация ядра должна включать в себя все промежуточные устройства для драйверов, которые предполагают их наличие. С другой стороны, если в системе отсутствуют устройства ATA RAID, накопители на гибких магнитных дисках или ленточные приводы, вы можете удалить эти устройства из своего ядра.

Уменьшение ядра

Когда-то, давным-давно, память стоила очень дорого и карты памяти имели небольшую емкость. Когда в системе имелось 128 Мбайт, приходилось экономить каждый бит, поэтому было важно получить ядро как можно меньшего объема. В наши дни даже ноутбуки имеют по 2 Гбайта ОЗУ, и размер ядра перестал играть такую важную роль. Удаление ненужных драйверов из ядра перестало быть насущной необходимостью, но мы не будем замалчивать эту тему и будем учиться собирать ядро так, чтобы потом, когда появится такая необходимость, вам не пришлось бы изучать все сначала. В качестве учебного примера мы пройдем процесс уменьшения размеров ядра, но не считайте это жизненно важным или необходимым этапом.

Удаление записей из конфигурации ядра производится простым комментированием строк.

Типы CPU

Для большинства архитектур FreeBSD поддерживает всего два типа микропроцессоров (CPU). В архитектуре i386 – три. Удаление ненужных типов CPU из конфигурации приведет к созданию ядра, которое полностью использует преимущества, предлагаемые имеющимся микропроцессором. Например, рассмотрим процессоры Pentium и Pentium II с поддержкой инструкций MMX. Если эти инструкции поддерживаются микропроцессором, было бы желательно воспользоваться их преимуществами. С другой стороны, удаление из конфигурации упоминания о неиспользуемых типах CPU приведет к созданию ядра, которое будет способно работать только с одним типом CPU.

Вам необходимо оставить только тот тип CPU, который имеется в системе. Если тип CPU неизвестен, узнать его можно из файла dmesg.boot. Файл dmesg.boot на моем ноутбуке содержит следующие строки:

CPU: AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ (2200.10-MHz 686class CPU) Origin = «AuthenticAMD» Id = 0x20fb1 Stepping = 1

Features=0x178bfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,C MOV,PAT,PSE36,CLFLUSH,MMX,FXSR,SSE,SSE2,HTT>

Жирным шрифтом выделена часть строки, которая сообщает, что в системе присутствует микропроцессор 686-class CPU. Это означает, что я могу удалить инструкцию cpu, описывающую микропроцессор I486_CPU, что сделает мое ядро меньше и быстрее. В результате при компиляции ядра, вместо медленного универсального кода, будут реализованы оптимизации, характерные для процессора 686-class. (Кроме того, это 64-битовый i386-совместимый процессор, который позволяет запускать версии FreeBSD для архитектур i386 и amd64, как обсуждалось в главе 1. Однако в примерах мы остановимся на архитектуре i386, которой наверняка обладает большинство читателей.)

Основные параметры

Вслед за записями, определяющими выбор типа CPU, имеется целый список параметров основных служб FreeBSD, таких как TCP/IP и файловые системы. Для средней системы необязательно присутствие всех этих особенностей, но их наличие увеличивает гибкость системы. Также можно обнаружить редко используемые параметры, которые можно удалить. Здесь не обсуждаются все возможные параметры ядра, а представлены только наиболее общие из них и специфичные примеры для их различных типов. Особым образом будут отмечены те, что имеют отношение к серверу Интернета. Рассмотрим следующие «опции»:

 

#options       SCHED_ULE

options        SCHED_4BSD

options        PREEMPTION

# ULE scheduler

# 4BSD scheduler

# Enable kernel thread preemption

 

Эти параметры управляют внутренним алгоритмом планирования FreeBSD. Планирование будет обсуждаться в главе 12. Возможность вытеснения (preemption) повышает эффективность FreeBSD в многозадачном режиме.

options        INET            # InterNETworking

options        INET6           # IPv6 communications protocols

 

Эти параметры обеспечивают поддержку сетевых протоколов. Параметр INET обеспечивает поддержку старомодного стека протоколов TCP/IP, тогда как параметр INET6 – поддержку IPv6. Программное обеспечение UNIX-подобных систем зависит от наличия поддержки TCP/IP, поэтому параметр INET следует оставить. Версия IPv6 пока не получила широкого распространения – рано или поздно вы придете к пониманию, что ее время еще не наступило, поэтому при желании этот параметр можно удалить.

options       FFS

options       SOFTUPDATES

options       UFS_ACL

options       UFS_DIRHASH

# Berkeley Fast Filesystem

# Enable FFS soft updates support

# Support for access control lists

# Improve performance on big directories

 

FFS – это стандартная файловая система для FreeBSD, а остальные параметры связаны с ней. Параметр SOFTUPDATES – это метод обеспечения целостности диска даже в случае некорректного завершения системы. Списки управления доступом UFS позволяют определять весьма подробные права доступа к файлам, а параметр UFS_DIRHASH обеспечивает поддержку индексирования каталогов, что повышает скорость работы с каталогами, содержащими тысячи файлов. Более подробно параметры FFS будут рассматриваться в главе 8.

options        MD_ROOT         # MD is a potential root device

 

Этот параметр (и все остальные параметры, оканчивающиеся на _ROOT) позволяет использовать в качестве дискового устройства для корневого раздела другие файловые системы, отличные от FFS. Инсталлятор использует в качестве корневой файловой системы устройство памяти (MD). Если вы используете бездисковые системы (глава 20), вам потребуется поддержка NFS в качестве корневого раздела. Если вы устанавливаете FreeBSD на стандартный компьютер – с жестким диском и клавиатурой, то все эти параметры вам не потребуются.

options        NFSCLIENT       # Network Filesystem Client

options        NFSSERVER       # Network Filesystem Server

 

Эти два параметра обеспечивают поддержку сетевой файловой системы (Network File System, NFS) (глава 8). Параметр NFSCLIENT позволит монтировать разделы, которые обслуживаются другим компьютером в сети, а параметр NFSSERVER позволит обеспечить доступ к своим разделам для других компьютеров.

options        MSDOSFS         # MSDOS filesystem

options        CD9660

options        PROCFS

options        PSEUDOFS

# ISO 9660 filesystem

# Process filesystem (requires PSEUDOFS)

# Pseudo-filesystem framework

 

Эти параметры обеспечивают поддержку редко используемых файловых систем, таких как FAT, CD, файловой системы процессов и инфраструктуры псевдофайловой системы. Все эти файловые системы будут рассматриваться в главе 8, но все функциональные возможности, которые необходимы для работы с ними, доступны в виде модулей ядра, в тех редких случаях, когда в этом возникает необходимость.

options        COMPAT_43TTY    # BSD 4.3 TTY compat [KEEP THIS!]

options        COMPAT_FREEBSD4 # Compatible with FreeBSD4

options        COMPAT_FREEBSD5 # Compatible with FreeBSD5

options        COMPAT_FREEBSD6 # Compatible with FreeBSD6

 

Эти параметры совместимости позволяют запускать программное обеспечение, скомпилированное для устаревших версий FreeBSD, а также программное обеспечение, которое требует определенной версии ядра, что было необходимо в более ранних версиях FreeBSD. Если вы устанавливали систему с самого начала, тогда вам, возможно, не требуется совместимость с FreeBSD 4, 5 или 6, однако существует достаточно большое число программных продуктов, ориентированных на работу в среде 4.3 BSD. Оставьте параметр COMPAT_43TTY, иначе ваша система может оказаться неработоспособной.

options        SCSI_DELAY=5000 # Delay (in ms) before probing SCSI

 

Параметр SCSI_DELAY задает количество миллисекунд, в течение которых после обнаружения контроллеров SCSI система FreeBSD ожидает перед опрашиванием устройств SCSI, давая им время «раскрутиться» и идентифицировать себя на шине SCSI. Если в системе нет устройств SCSI, данную строку можно удалить. Если установлены древние аппаратные устройства SCSI, которые поднимаются медленно, как больной слон, то паузу можно увеличить до 15 000 (15 секунд).

options        SYSVSHM

options        SYSVMSG

options        SYSVSEM

# SYSV-style shared memory

# SYSV-style message queues

# SYSV-style semaphores

 

Эти параметры обеспечивают поддержку разделяемой памяти и межпроцессных взаимодействий в стиле System V. На эту возможность опираются многие программы управления базами данных.

options        AHC_REG_PRETTY_PRINT # Print register bitfields in debug

# output. Adds ~128k to driver.

options        AHD_REG_PRETTY_PRINT # Print register bitfields in debug

# output. Adds ~215k to driver.

Параметры, подобные этим, эффективны только в случае использования аппаратных устройств, на которые они ссылаются. В противном случае они могут быть удалены.

Более одного процессора

Следующие две записи активируют симметричную многопроцессорную обработку (Symmetric Multiprocessing, SMP) в ядрах, предназначенных для работы в архитектуре i386:

options        SMP             # Symmetric MultiProcessor Kernel

device         apic            # I/O APIC

 

Параметр SMP предписывает ядру производить планирование работы процессов на нескольких CPU, а параметр apic обеспечивает поддержку ввода/вывода для ядер SMP. Реализация i386 SMP в системе FreeBSD поддерживает только те многопроцессорные системы, которые отвечают спецификации SMP компании Intel и куда не входят 386 или 486 SMP-системы. (Для других платформ, таких как sparc64, имеются свои собственные стандарты, поэтому для них реализация SMP выполнена на очень высоком уровне.) Система FreeBSD поддерживает многопроцессорные системы, построенные только на базе процессоров Pentium и выше. В более старых версиях FreeBSD ядра с поддержкой SMP плохо или вообще не загружались на однопроцессорных системах – непроизводительные затраты на управление данными для нескольких процессоров создавали дополнительные задержки в системе. С течением времени эта проблема была ликвидирована и теперь FreeBSD распространяется с поддержкой SMP, включенной по умолчанию.

Драйверы устройств

Вслед за параметрами в файле конфигурации расположены записи с настройками драйверов устройств, которые сгруппированы вполне очевидным образом.

Первые записи – это шины, например device pci и device eisa. Убирать их следует лишь в том случае, если в системе действительно нет таких шин. Велико количество систем «без поддержки традиционных устройств» (legacy-free), в которых шина ISA скрыта где-то внутри.

Далее следует то, что большинством рассматриваются как драйверы устройств, – записи для накопителей на гибких магнитных дисках, контроллеров SCSI, контроллеров RAID и т. д. Если ваша цель уменьшить размер ядра, то данный раздел – хорошее место для решительного сокращения. Удалите все драйверы устройств, которые отсутствуют в компьютере. Здесь вы также найдете раздел драйверов устройств для клавиатур, видеокарт, портов PS/2 и т. д. Эти записи едва ли стоит удалять.

Раздел драйверов сетевых карт содержит довольно длинный список и по своему размеру напоминает разделы с драйверами устройств IDE и SCSI. Вы можете удалить из конфигурации любые сетевые карты, которые не используете.

Мы не будем перечислять здесь все драйверы устройств, поскольку в этом мало практической пользы, разве что ознакомиться с перечнем оборудования, которое поддерживалось на момент, когда я писал этот раздел. Чтобы ознакомиться с перечнем оборудования, поддерживаемым вашей версией FreeBSD, загляните в примечания к выпуску (release notes).

Псевдоустройства

В нижней части файла настройки ядра GENERIC представлен список псевдоустройств. Как подсказывает их название, они всецело создаются программными методами. Ниже приводится описание некоторых из наиболее часто используемых псевдоустройств.

device         loop            # Network loopback

Это петлевой интерфейс, позволяющий системе взаимодействовать с самой собой через сетевые сокеты, с использованием сетевых протоколов. Сетевые соединения во всех подробностях будут рассматриваться в следующей главе. Вас может удивить, как много программ используют петлевой интерфейс; его следует оставить.

device         random          # Entropy device

Это устройство обеспечивает генерацию псевдослучайных чисел, необходимых в операциях шифрования и таких важных программах, как игры. FreeBSD обеспечивает поддержку разнообразных источников случайных чисел, и все они объединяются в виде устройств псевдослучайных чисел /dev/random и /dev/urandom.

device         ether           # Ethernet support

Ethernet обладает массой особенностей, характерных для устройств, и потому FreeBSD представляет его как устройство. Оставьте эту строку, если ваша цель не изучение системы.

device         sl              # Kernel SLIP

device         ppp             # Kernel PPP

Псевдоустройство sl предназначено для поддержки межсетевого протокола для последовательного канала (Serial Line Internet Protocol, SLIP), а устройство ppp поддерживает протокол «точка-точка» (Point to Point Protocol, PPP) на уровне ядра. Оба они давно устарели и не требуются для поддержки PPP в пространстве пользователя, если, конечно, у вас нет особых требований.

device         tun             # Packet tunnel.

Псевдоустройство tun – это логический пакетный канал (logical packet tunnel). Используется различными программами для обмена пакетами с ядром. Такое псевдоустройство необходимо для поддержки PPP средствами, не входящими в ядро (userland PPP), – обычными коммутируемыми соединениями.

device         pty             # Pseudo-ttys (telnet etc)

Псевдоустройство pty – это псевдотерминал. Когда вы подключаетесь к системе по протоколам telnet или SSH (глава 15), FreeBSD должна иметь возможность отслеживать терминальные сеансы, выводить символы на экран и читать ввод с клавиатуры. Система обслуживает удаленное соединение как обычный физический монитор и клавиатуру. Псевдотерминал – это псевдоустройство, напоминающее терминал, связанное с соединением.

device         md              # Memory «disks»

Псевдоустройство md позволяет хранить файлы в памяти. Это очень удобно для организации очень быстрых хранилищ временных данных, но об этом мы поговорим в главе 8. Для большинства (но не для всех) серверов Интернета диски в памяти – это просто непродуктивное растрачивание оперативной памяти. Кроме того, диски в памяти могут использоваться для монтирования и доступа к образам дисков. Если вы не используете диски в памяти, этот параметр можно удалить из ядра.

Отключаемые устройства

Наконец, после псевдоустройств в конфигурационном файле GENERIC можно найти поддержку FireWire и устройств USB. Эти функциональные возможности всегда оформляются в виде модулей, так как представляют устройства, которые могут присутствовать, а могут и не присутствовать в системе.

Сборка ядра

После прочтения предыдущего раздела вы должны быть в состоянии спроектировать минимальную конфигурацию ядра. Перед тем как добавлять в ядро поддержку каких-либо других возможностей, я рекомендую собрать и запустить описанное минимальное ядро. Это позволит понять, что действительно необходимо для надлежащей работы ядра и какая требуется дополнительная настройка.

Вам необходимо указать имя файла, который содержит конфигурацию вашего ядра, либо в командной строке, либо в файле /etc/make.conf, либо в файле /etc/src.conf, в виде переменной окружения KERNCONF.

# cd /usr/src
# make KERNCONF=MYKERNEL kernel

Процесс сборки начинается с запуска команды config(8), для поиска синтаксических ошибок в файле конфигурации. Если config(8) обнаружит какие-либо ошибки, она сообщит о них и прекратит работу. Некоторые сообщения об ошибках довольно очевидны. Например, можно случайно удалить поддержку файловой системы UNIX (UNIX File System, UFS), но включить поддержку инициализации UFS. Одна функция не может обойтись без другой, поэтому config точно скажет, в чем состоит ошибка. Другие сообщения об ошибках могут выглядеть странно и непонятно, и тогда для выяснения причин может потребоваться длительное время, как, например, при получении следующего сообщения:

HUMVEE: unknown option «NET6»

NET6 – это же параметр, активирующий поддержку IPv6, разве не так? Нет, эту поддержку активирует параметр INET6. Сообщения об ошибках в достаточной мере описывают проблему, особенно теперь, когда вы познакомились со всеми параметрами, поддерживаемыми ядром. Внимательно читайте сообщения об ошибках!

Если config(8) не нашла ошибок, остается только ждать. Процесс сборки ядра на 486 компьютере может занимать несколько часов, но меньше часа на современной и быстрой системе. При этом по экрану будут пробегать загадочные сообщения о ходе компиляции. По окончании сборки система переименует текущее ядро в /boot/kernel.old, а новое ядро будет сохранено в виде файла /boot/kernel. Когда все закончится, перезагрузите сервер и посмотрите на сообщения, появляющиеся во время загрузки.

Copyright (c) 1992-2006 The FreeBSD Project.

Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994

The Regents of the University of California. All rights reserved.  FreeBSD 7.0-CURRENT #0: Thu May 11 01:16:19 EDT 2006
[email protected]:/usr/src/sys/compile/HUMVEE

Во время загрузки FreeBSD точно сообщит, какое ядро было загружено  и где это ядро было собрано . Поздравляю, вы только что собрали ядро!

Выявление неполадок при создании ядра

Если собрать ядро не удалось, то для выявления неполадок прежде всего необходимо изучить последние строки, выданные при компиляции. Некоторые из этих строк могут показаться непонятным шифром, а другие достаточно очевидны. Важно помнить, что сообщения вида «Stop in имя некоторого каталога» абсолютно бесполезны – нужные нам сообщения об ошибках находятся перед ними. О том, как решать эти проблемы, мы говорили в главе 1: берете текст сообщения об ошибке и обращаетесь за помощью к поисковой системе. Как правило, ошибки времени компиляции вызваны ошибками в конфигурации.

К счастью, во FreeBSD перед установкой чего-либо надо полностью скомпилировать все ядро. Благодаря этому система защищена, а результаты неудачной компиляции по-прежнему находятся в каталоге сборки.

Загрузка с запасного ядра

Итак, что делать, если новое ядро не работает или работает неустойчиво? Возможно, при конфигурировании не был указан драйвер устройства либо удалено псевдоустройство ppp и не удается установить коммутируемое соединение с Интернетом. Без паники! Старое ядро сохранено, верно? Хорошо. Вот что следует предпринять.

В главе 3 мы обсуждали механизм загрузки альтернативного ядра. Мы пройдем этот процесс еще раз, но, чтобы увидеть некоторые пояснения, касающиеся подробностей управления загрузчиком, вам может потребоваться вернуться к более раннему разделу. А теперь сосредоточим свое внимание на причинах, которые могут вынудить произвести загрузку с запасного ядра, и на том, как сделать это правильно.

Для начала необходимо решить, какое ядро загружать. Старое ядро должно находиться в каталоге /boot – в этом разделе предполагается, что необходимо загрузить ядро /boot/kernel.good. Запустите перезагрузку и прервите ее, чтобы получить доступ к командной строке загрузчика. Вспомните, мы говорили, что к моменту, когда FreeBSD предоставит доступ к командной строке загрузчика, ядро уже было загружено, поэтому в первую очередь необходимо выбросить плохое ядро за борт:

ok unload

Теперь можно загрузить требуемое ядро, а также модуль ACPI (если он используется) и любые другие модули ядра, которые обычно загружаются на этапе запуска системы:

ok load /boot/kernel.good/kernel ok load /boot/kernel.good/acpi.ko ok boot

После этого система будет загружена на старом ядре.

Включения, исключения и расширения ядра

Теперь, когда вы научились собирать ядро, можно попробовать включить свою фантазию и посмотреть, как можно использовать включения, ключевые слова с префиксом no и файл NOTES.

NOTES

Ядро FreeBSD включает в себя самые разнообразные функциональные возможности, которые не включены в GENERIC. Многие из этих возможностей предназначены для построения весьма специфических систем или сетей особого вида. Полный перечень особенностей, зависящих от аппаратного обеспечения, можно найти в файле NOTES, в каталоге с конфигурациями ядра для каждой из аппаратных архитектур, например /sys/amd64/conf/NOTES. Перечень особенностей, поддерживаемых системой FreeBSD и не зависящих от аппаратного окружения, можно найти в файле /sys/conf/NOTES. Если у вас имеется аппаратное устройство, которое не поддерживается ядром GENERIC, загляните в файл NOTES. Некоторые из перечисленных в этом файле особенностей имеют неясное назначение, но если у вас имеется определенное устройство, то вы сможете разобраться, какая запись ему соответствует. Давайте взглянем на типичную запись из файла NOTES:

# CPU_SOEKRIS enables support www.soekris.com hardware.

#

options CPU_SOEKRIS

Soekris – это название производителя небольших систем для встраиваемых устройств. Об этих системах мы поговорим в главе 21 – они не настолько распространены, чтобы эта запись попала в GENERIC, но если у вас имеется одно из таких устройств, вы можете использовать параметр CPU_SOEKRIS, чтобы активировать особые функциональные возможности этого микропроцессора.

Если в файле NOTES перечислены все особенности для каждого из возможных устройств, почему бы не использовать его как основу для сборки собственного ядра? Во-первых, такое ядро расходовало бы больший объем памяти, чем ядро GENERIC. Несмотря на то, что даже небольшие современные компьютеры имеют достаточно памяти для запуска ядра GENERIC без каких-либо проблем, тем не менее, если ядро увеличится в размерах в десять раз без заметного увеличения функциональности, люди начнут недоумевать. Кроме того, многие параметры настройки являются взаимно исключающими. В файле NOTES можно отыскать параметры для микропроцессоров Athlon, Cyrix, IBM, параметры, предназначенные для учета некоторых особенностей различных версий плат, и т. д.

Включения и исключения

Механизм конфигурирования ядра FreeBSD обладает двумя интересными возможностями, которые способны упростить обслуживание ядра: ключевые слова с префиксом no и включения.

Возможность подключения позволяет добавить отдельный файл в конфигурацию ядра. Например, если имеется конфигурация ядра, которая описана как «GENERIC с парой дополнительных настроек», к ней можно было бы подключить конфигурацию GENERIC с помощью оператора include:

include GENERIC

Так, например, если необходимо собрать ядро, которое обладает функциональностью GENERIC, но кроме того поддерживает микропроцессор Soekris, можно было бы создать конфигурацию, составленную из следующих строк:

ident          MYKERNEL

include        GENERIC

options        CPU_SOEKRIS

 

Вы можете подумать, что такой подход дает немного больше, чем простое копирование и редактирование файла GENERIC, и будете правы.

Какие преимущества дает такой подход? Дело в том, что по мере обновления FreeBSD конфигурация GENERIC может изменяться. Например, конфигурация GENERIC в версии FreeBSD 7.1 несколько отличается от той, что используется в версии 7.0. При рассматриваемом подходе ваша конфигурация будет корректной в обеих версиях FreeBSD и в обеих по праву может называться «GENERIC плюс дополнительные параметры».

Такой подход отлично подходит для случаев включения элементов конфигурации, но не годится для случая исключения элементов из ядра. Например, любые микропроцессоры Soekris используются в небольших системах, не имеющих карты SCSI или RAID. В этом случае можно было бы дополнить свою конфигурацию объявлениями nodevice, исключающими поддержку всех этих устройств. Запись nodevice отменяет ранее объявленное включение устройства. Аналогичным образом ключевое слово nooption запрещает активизацию указанного параметра.

Наглядным примером использования такой методики может служить конфигурация ядра PAE. PAE – это конфигурация, которая используется в системах i386 с объемом памяти более 4 Гбайт, о чем будет говориться ниже, в этой же главе. Многие устаревшие устройства не в состоянии работать на компьютерах с таким объемом памяти, поэтому они должны быть исключены из конфигурации. Неважно, насколько велики изменения, произошедшие в вашей системе FreeBSD в результате обновления, вы всегда точно будете знать, что ядро PAE – это «GENERIC плюс возможности PAE минус все драйверы, которые не способны работать в конфигурации PAE».

Как с помощью параметров ядра исправлять проблемы

Некоторые параметры настройки ядра могут использоваться исключительно в случае появления определенных проблем. Например, пару лет назад у моего знакомого были веб-серверы, собранные на аппаратных средствах i386. Когда одному серверу пришлось обслуживать по нескольку сотен веб-страниц в секунду, на консоли стали появляться сообщения, подобные этому:

Jun 9 16:23:17 ralph/kernel: pmap_collect: collecting pv entries —

suggest increasing PMAP_SHPGPERPROC

 

Спустя пару часов после появления сообщения происходила авария системы. Совершенно очевидно, что мы с большой серьезностью отнеслись к этому случаю, и я произвел поиск в Интернете и просмотрел содержимое файла NOTES, где обнаружил следующую запись:

# Set the number of PV entries per process. Increasing this can

# stop panics related to heavy use of shared memory. However, that can

# (combined with large amounts of physical memory) cause panics at

# boot time due the kernel running out of VM space.

# (Устанавливает количество записей (pv-entry) таблицы страниц

# на один процесс. Увеличение этого числа может предотвратить неполадки,

# связанные с нехваткой разделяемой памяти. Однако при большой емкости

# физической памяти это может вызвать неполадки во время начальной загрузки

# из-за выхода за пределы пространства виртуальной памяти.)

#

# If you’re tweaking this, you might also want to increase the sysctls

# «vm.v_free_min», «vm.v_free_reserved», and «vm.v_free_target».

# (При настройке этого параметра надо также увеличить значения:

# sysctls «vm.v_free_min», «vm.v_free_reserved» и «vm.v_free_target».)

#

# The value below is the one more than the default.

# (Значение,приведенное ниже, на единицу превышает значение по умолчанию.)

#

options PMAP_SHPGPERPROC=201

 

Прочитав это объяснение, мы приступили к решению проблемы. Прежде всего, сохранили старое ядро в /boot/kernel.pmapcrash. Это было не самое лучшее ядро, но оно обеспечивало работоспособность системы хотя бы на несколько часов. Затем мы увеличили значение PMAP_SHPGPERPROC до 400, а емкость оперативной памяти увеличили до 192 Мбайт. (Да, эта недорогая система обслуживала несколько сотен веб-страниц в секунду, имея в распоряжении 64 Мбайт оперативной памяти, один диск IDE и CPU Celeron 433!) После сборки нового ядра проблема была устранена, а период работоспособного состояния сервера достиг нескольких месяцев. В версии FreeBSD 7 данный параметр ядра можно настроить через sysctl, прямо во время работы системы, однако в ядре существует еще множество параметров, которые можно изменить только таким способом.

Не будь возможности тонкой настройки ядра, единственным выходом стала бы покупка дополнительных аппаратных средств. Даже при том, что аппаратное обеспечение этой системы характеризуется низкой производительностью, нам удалось обеспечить устойчивость к высоким нагрузкам всего лишь за счет программной настройки и покупки небольшого количества памяти. В системе FreeBSD имеется большое число параметров, подобных этому, которые предназначены для особых ситуаций, и они скажут вам об этом, стоит только уделить им чуть больше внимания. (Замечу, что если вы просто пытаетесь направо и налево тратить свои деньги, я готов проявить милосердие к свободной наличности и, уверяю вас, смогу предоставить этим деньгам новый кров, где они будут высоко оценены.)

Распространение ядра

При наличии нескольких идентичных серверов не надо вручную собирать ядро на каждом из них; ядро, специально созданное для одного сервера, можно установить на остальных. В конце концов, ядро и модули к нему – это всего лишь файлы на диске.

Прежде всего, создайте и установите одно ядро и тщательно протестируйте его. Затем заархивируйте /boot/kernel с помощью tar и скопируйте тарбол на остальные серверы. Сохраните текущее ядро на каждом из них и разархивируйте тарбол, чтобы установить новый файл /boot/kernel. Перезагрузитесь, и дело сделано!

Удаленное тестирование ядра

Вполне обычное дело, когда администрирование системы FreeBSD производится удаленно, например, когда сервер находится в другом, закрытом помещении. У вас может не быть последовательной консоли, вследствие чего становится невозможным получить доступ к командной строке загрузчика. Самое большее, на что можно надеяться в таких ситуациях, это то, что у вас будет некто, кто сможет подойти к компьютеру и нажать кнопку питания. Как в таких обстоятельствах можно протестировать новое ядро? Здесь хорошо бы иметь возможность попробовать загрузить новое ядро и если что-то пойдет не так – выполнить перезагрузку с рабочим ядром. И такая возможность есть, она называется однократная тестовая загрузка. Здесь вам пригодится nextboot(8).

nextboot(8) – это способ сказать: «Загрузи это ядро в следующий раз, но только один раз». Команда nextboot принимает единственный аргумент –k, параметром которого является имя каталога с тестовым ядром, вложенного в каталог /boot. Например, я собрал и установил новое ядро, мне нужно однократно загрузить новое ядро, а если оно окажется неработоспособным, то на следующей перезагрузке должно быть загружено предыдущее ядро. Прежде всего, необходимо скопировать новое ядро в каталог, отличный от /boot/kernel, а в /boot/kernel должно находиться рабочее ядро.

# mv /boot/kernel /boot/kernel.test
# mkdir /boot/kernel
# cp /boot/kernel.good/* /boot/kernel/

Можно заранее предусмотреть установку ядра в данный каталог, установив значение переменной INSTKERNAME при сборке ядра. Дайте ядру имя во время установки ядра, и утилита make(1) автоматически поместит собранное ядро в нужное место:

# cd /usr/src
# make KERNCONF=TESTKERNEL INSTKERNAME=test kernel

Эта команда установит ядро как /boot/kernel.test.

Теперь, когда имеется рабочее ядро, установленное как ядро по умолчанию, и тестовое ядро как /boot/kernel.test, можно вызвать команду nextboot(8) и передать ей тестовое ядро в виде параметра ключа –k, указав имя каталога, вложенного в каталог /boot:

# nextboot k kernel.test

На следующей перезагрузке системы загрузчик запустит ядро из /boot/ kernel.test вместо /boot/kernel и заодно сотрет файл с настройками, где говорится о необходимости загрузить тестовое ядро. После этого при следующей перезагрузке будет загружено стандартное ядро. Вся хитрость состоит в том, чтобы рабочее ядро находилось в каталоге /boot/ kernel. Если новое ядро хорошо себя зарекомендовало, можно выполнить следующие команды:

# mv /boot/kernel /boot/kernel.previous # mv /boot/kernel.test /boot/kernel

Вуаля! И тестовое ядро превратилось в рабочее.

Осторожно – nextboot!

В руководстве говорится, что nextboot(8) выполняет запись в корневую файловую систему до того, как она пройдет проверку целостности на этапе загрузки. Это означает, что в случае некорректного завершения системы до момента загрузки нового ядра возможно, что nextboot повредит файловую систему. В действительности утилита nextboot(8) не выделяет новое дисковое пространство, она просто редактирует файл, который уже существует в системе, поэтому риск повреждения файловой системы сводится к минимуму.

Составляющие ядра, о которых следует знать

Для этого раздела лучше подошел бы заголовок «Параметры ядра, о которые можно споткнуться, если не знать, для чего они нужны». Если кто-то сообщает вам, что у вас наблюдаются проблемы с ACPI, вы должны понимать, о чем идет речь. Когда система извергает страшное проклятие: «lock order reversals» (аннулирован запрос на блокировку), вы должны знать, что неприятности вам гарантированы. Основные источники проблем – это ACPI, PAE, SMP и аннулирование запроса на блокировку.

ACPI

Усовершенствованный интерфейс управления конфигурированием и энергопотреблением (Advanced Configuration and Power Interface, ACPI) отвечает за низкоуровневое конфигурирование аппаратного обеспечения, режима электропитания и т. п. Это следующий этап развития устаревших протоколов, таких как Plug-and-Play, системы настройки аппаратного обеспечения PCI BIOS и APM (Advanced Power Management – усовершенствованное управление питанием). Как и в других UNIX-подобных операционных системах, при реализации ACPI в системе FreeBSD была использована справочная информация, представленная компанией Intel.

PAE

Это просто протокол конфигурирования аппаратного обеспечения, какие тут могут быть ошибки? Скажем так, не все производители аппаратных компонентов реализуют поддержку ACPI в точном соответствии со спецификациями, скорее, они реализуют достаточный объем функций, чтобы обеспечить совместимость своей аппаратуры с операционными системами компании Microsoft. Это означает, что все остальные, которые используют другие операционные системы, должны искать способы обхода этих недостатков. FreeBSD также включает в себя различные обходные пути для таких неполных реализаций ACPI, но иногда до их выхода в свет проходит некоторое время.

Кроме того, в первых моделях аппаратных средств, использовавших ACPI, часто обнаруживались проблемы с самим ACPI. Как и в случае с любым другим сложным протоколом, первым разработчикам приходилось учиться применять этот протокол на практике. Если ваши аппаратные компоненты были собраны в этот период, вам может потребоваться вообще запретить использование ACPI, поместив строку hint.acpi.0.disabled=1 в файл /boot/loader.conf. Если у вас есть подозрения на проблемы с ACPI в вашем аппаратном окружении, можно попробовать запретить использование ACPI однократно, выбрав соответствующий пункт меню загрузки.

В течение многих лет компьютеры с архитектурой i386 имели свойственное им ограничение – они могли иметь не более 4 Гбайт памяти. В то время компьютеры со 128 Мбайт памяти рассматривались как высокопроизводительные серверы, но к настоящему моменту развитие технологий сделало преодоление этого барьера не только мыслимым, но и реальным. Подобные ограничения существовали и раньше, начиная от предела в 640 Кбайт памяти для IBM PC и заканчивая пределом в 8 Гбайт для жестких дисков. Разработчики архитектуры должны выбрать некоторые пределы и попытаться установить их как можно выше, чтобы потом не волноваться о них в течение ближайших десяти лет или что-то около того. Механизм расширения пространства физических адресов (Physical Address Extensions, PAE) позволил поднять планку ограничения на объем памяти до 64 Гбайт, чего должно хватить на ближайшие несколько лет. К тому времени, когда такие объемы памяти станут обычным делом, большинство новых систем будут работать в 64-битовом режиме, что позволит поднять ограничения намного выше.

Но не все устройства совместимы с PAE, поэтому PAE не может включаться в ядро GENERIC. Конфигурацию ядра с поддержкой PAE можно найти в файле /sys/i386/conf/PAE. Поддержка PAE необходима только для архитектуры i386 – amd64, sparc64 и другие новейшие архитектуры имеют другие ограничения на объем памяти, которые еще не были достигнуты.

Поддержку PAE нельзя запретить на этапе загрузки или во время работы системы – она либо присутствует в ядре, либо нет.

Симметричная многопроцессорная обработка

Симметричная многопроцессорная обработка (Symmetric Multiprocessing, SMP) означает наличие в системе нескольких микропроцессоров общего назначения. В теории операционная система равномерно распределяет рабочую нагрузку между несколькими процессорами. Но на самом деле все гораздо сложнее, чем кажется на первый взгляд, по причинам, которые будут рассматриваться в главе 12. Для обслуживания нескольких процессоров ядро должно включать options SMP и device apic.

В некоторых случаях в отдельных частях системы могут появляться проблемы, связанные с поддержкой SMP. До выяснения источника проблем может оказаться полезным временно отключить поддержку SMP. Если проблема присутствует при включенной поддержке SMP и пропадает при ее отключении, это поможет идентифицировать проблему. Запретить поддержку SMP можно на этапе загрузки, установив значение параметра kern.smp.disabled равным 1. Аналогичным образом можно отключить поддержку APIC, побочным эффектом чего является отключение поддержки SMP. Запретить поддержку APIC можно, установив значение параметра hint.apic.0.disabled=»1″.

Аннулирование запроса на блокировку

Ключевым элементом реализации поддержки SMP является блокировка ядра. Хотя вы, как пользователь, не должны беспокоиться по поводу блокировок ядра, тем не менее иногда при работе с определенными версиями FreeBSD (в частности, -current) в консоли могут появляться сообщения об аннулировании запросов на блокировку. Эти сообщения генерируются механизмом отладки ядра WITNESS (глава 13) и означают, что блокировки в ядре выполняются не так, как было задумано разработчиками. По большей части эти сообщения не представляют ничего опасного, но они выглядят устрашающе и действительно свидетельствуют о потенциальных проблемах.

Если вам встретятся подобные сообщения, лучше всего узнать, не сообщалось ли что-нибудь об этом конкретном сообщении ранее. Для этого можно выполнить поиск в Интернете по тексту сообщения. Можно также поискать на странице Lock Order Reversal веб-сайта FreeBSD (к моменту написания этих строк поддерживалась Бьерном Зибом (Bjoern Zeeb)) и узнать, упоминается ли данное сообщение здесь. Если поиск сообщения, встретившегося у вас, не дал результатов, вам следует сообщить об этом разработчикам FreeBSD, написав письмо в рассылку FreeBSD[email protected].

Теперь у вас имеется объем знаний, достаточный для обслуживания ядра FreeBSD. Пойдем дальше и посмотрим, что можно сделать с сетью.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Закончите арифметическое действие * Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.