Wiki

Глава 1. Введение.


1.1. Что такое "Модуль Ядра"?

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

Так что же такое "модуль ядра"? Модуль -- это некий код, который может быть загружен или выгружен ядром по мере необходимости. Модули расширяют функциональные возможности ядра без необходимости перезагрузки системы. Например, одна из разновидностей модулей ядра, драйверы устройств, позволяют ядру взаимодействовать с аппаратурой компьютера. При отсутствии поддержки модулей нам пришлось бы писать монолитные ядра и добавлять новые возможности прямо в ядро. При этом, после добавления в ядро новых возможностей, пришлось бы перезагружать систему.


1.2. Как модули попадают в ядро?

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

Как же модули загружаются ядром? Когда ядро обнаруживает необходимость в тех или иных функциональных возможностях, еще не загруженных в память, то демон kmod [1] вызывает утилиту modprobe, передавая ей строку в виде:

  • Название модуля, например softdog или ppp.

  • Универсальный идентификатор, например char-major-10-30.



Если утилите modprobe передается универсальный идентификатор, то она сначала пытается отыскать имя соответствующего модуля в файле /etc/modules.conf, где каждому универсальному идентификатору поставлено в соответствие имя модуля, например:

alias char-major-10-30 softdog    


Это соответствует утверждению: "Данному универсальному идентификатору соответствует файл модуля softdog.ko".

Затем modprobe отыскивает файл /lib/modules/version/modules.dep, чтобы проверить -- не нужно ли загружать еще какие-либо модули, от которых может зависеть заданный модуль. Этот файл создается командой depmod -a и описывает зависимости модулей. Например, модуль msdos.ko требует, чтобы предварительно был загружен модуль fat.ko. Если модуль Б экспортирует ряд имен (имена функций, переменных и т.п.), которые используются модулем А, то говорят, что "Модуль А зависит от модуля Б".

И наконец modprobe вызывает insmod, чтобы сначала загрузить необходимые, для удовлетворения зависимостей, модули, а затем и запрошенный модуль. Вызывая insmod, утилита modprobe указывает ей каталог, /lib/modules/version/ [2] -- стандартный путь к модулям ядра. Утилита insmod ничего не "знает" о размещении модулей ядра, зато это "знает" утилита modprobe. Таким образом, если вам необходимо загрузить модуль msdos, то вам необходимо дать следующие команды:

insmod /lib/modules/2.6.0/kernel/fs/fat/fat.ko
insmod /lib/modules/2.6.0/kernel/fs/msdos/msdos.ko
 

или просто:

modprobe -a msdos   
 

В большинстве дистрибутивов Linux, утилиты modprobe, insmod, depmod входят в состав пакета modutils или mod-utils.

Прежде чем закончить эту главу, я предлагаю вкратце ознакомиться с содержимым файла /etc/modules.conf:

### This file is automatically generated by modules-update
#
# Please do not edit this file directly. If you want to change or add
# anything please take a look at the files in /etc/modules.d and read
# the manpage for modules-update.
#
### modules-update: start processing /etc/modules.d/aliases
# Aliases to tell insmod/modprobe which modules to use 
path[misc]=/lib/modules/2.6.?/local
keep
path[net]=~p/mymodules
options mydriver irq=10
alias eth0 eepro
 

Строки, начинающиеся с символа "#" являются комментариями. Пустые строки игнорируются.

Строка path[misc] сообщает modprobe о том, что модули ядра из категории misc следует искать в каталоге /lib/modules/2.6.?/local. Как видите, здесь вполне допустимы шаблонные символы.

Строка path[net] задает каталог размещения модулей категории net, однако, директива keep, стоящая выше, сообщает, что каталог ~p/mymodules не замещает стандартный путь поиска модулей (как это происходит в случае с path[misc]), а лишь добавляется к нему.

Строка alias говорит о том, что если запрошена загрузка модуля по универсальному идентификатору eth0, то следует загружать модуль eepro.ko

Вы едва ли встретите в этом файле строки, подобные:

alias block-major-2 floppy  
 

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


1.2.1. Прежде, чем продолжить

Прежде, чем мы приступим к программированию, необходимо обсудить еще ряд моментов. Любая система имеет свои отличительные черты и каждый из нас имеет разный багаж знаний. Написать, скомпилировать и запустить свою первую программу "Hello World!" для многих может оказаться довольно сложной задачей. Однако, после преодоления этого начального препятствия, работа, как правило, продвигается без особых проблем.


1.2.1.1. Механизм контроля версий

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


1.2.1.2. Работа в XWindow

Мы настоятельно рекомендуем скачать и опробовать все примеры, обсуждаемые в книге. Кроме того, мы настаиваем на том, чтобы всю работу, связанную с редактированием исходных текстов, компиляцией и запуском модулей, вы выполняли из текстовой консоли. Поверьте нашему опыту, XWindow не подходит для выполнения подобных задач.

Модули не могут использовать функцию printf() для вывода не экран, но они могут регистрировать сообщения об ошибках, которые в конечном итоге попадают на экран, но только в текстовой консоли. Если же модуль загружается из окна терминала, например xterm, то эти сообщения будут попадать только в системный журнал и не будут выводиться на экран. Чтобы видеть выводимые сообщения на экране, работайте в текстовой консоли (от переводчика: при опробовании примеров из книги мне не удалось вывести ни одного сообщения на экран, так что ищите ваши сообщения в системном журнале, в моем случае это был файл /var/log/kern.log).


1.2.1.3. Проблемы компиляции

Зачастую, дистрибутивостроители распространяют исходные тексты ядра, на которые уже наложены разные нестандартные заплаты. Это может породить определенные проблемы.

Не менее частый случай -- неполный набор заголовочных файлов ядра. Для сборки своих модулей вам потребуются многие заголовочные файлы ядра Linux. А закон Мэрфи гласит: "Отсутствовать будут как раз те файлы, в которых вы больше всего нуждаетесь".

Чтобы избежать этих двух проблем, мы рекомендуем собрать и установить наиболее свежее ядро. Скачать исходные тексты ядра вы сможете на любом из зеркал, распространяющих ядро Linux. За более подробной информацией обращайтесь к "Kernel HOWTO".

Как это ни покажется странным, но проблемы могут крыться и в компиляторе. По-умолчанию gcc может искать заголовочные файлы ядра совсем не там, куда вы их установили (как правило это каталог /usr/src/. Эта проблема легко преодолевается заданием ключа компиляции -I.