Введение
В нескольких предыдущих частях был сделан акцент на создании модулей ядра и их положении в общей архитектуре системы. Но, в конечном счёте, всё это сводится к вопросу: как правильно, гибко и наилучшим образом использовать модули? А использование в контексте модулей - это загрузка модулей в ядро и те возможности, с помощью которых программист может сделать этот процесс более управляемым.
Загрузка модулей
Ранее неоднократно показывалось, как использовать команду insmod
для загрузки только что собранных модулей. Но это был самый низкий уровень модульной подсистемы, так как вряд ли пользователь удовлетворится необходимостью поштучной загрузки всех модулей при каждой загрузке операционной системы Linux, да ещё и с необходимостью указания полного путевого имени каждого загружаемого модуля. С другой стороны, некоторая интегрированная среда, производящая загрузку всех необходимых модулей при загрузке системы, тоже представляла бы определённую проблему. Так, если загрузить один раз модуль (например, в порядке тестирования), который делает невозможной дальнейшую загрузку системы (терминальная ошибка), то эта ситуация воспроизводилась при каждой загрузке системы (для исправления ошибки загрузки нужна работающая система и редактор конфигураций, но для загрузки системы нужна исправленная конфигурация - получается порочный замкнутый круг). Для разрешения этой коллизии в системе оставлены два альтернативных способа загрузки модулей: команда insmod
и команда modprobe
.
Утилита insmod
получает имя файла модуля (с указанием полного путевого имени, если это необходимо, и расширения имени файла .ko) и пытается загрузить его без каких-либо проверок взаимосвязей, как отдельный автономный файл: либо он загружается, либо нет. Утилита modprobe работает более тонко: ей передаётся или универсальный идентификатор, или непосредственное имя модуля. Если modprobe получает универсальный идентификатор, то она сначала пытается найти соответствующее имя модуля в файле /etc/modprobe.conf (устаревшее поведение), или в любом из файлов *.conf в каталоге /etc/modprobe.d, где каждому универсальному идентификатору поставлено в соответствие имя файла модуля (записанное в строке alias ...
, см. modprobe.conf(5)
).
Далее утилита modprobe по имени модуля и по содержимому файла зависимостей /lib/modules/`uname -r`/modules.dep пытается установить зависимости запрошенного модуля: модули, от которых зависит запрошенный модуль, будут загружены до него самого. Понятно, что это рекурсивный процесс, и он будет продолжаться до тех пор, пока все зависимости не будут разрешены или не будет найдена зависимость от неизвестного модуля и, тем самым, установлена невозможность загрузки всей иерархии зависимых модулей, и как конечный итог загрузки запрошенного модуля, т.е. попытка оказывается неудачной.
Файл зависимостей modules.dep заранее формируется командой:
Этой же командой (время от времени) обновляется и большинство других файлов modules.* в этом каталоге:
$ ls /lib/modules/`uname -r`/modules.*
...
|
Интересующий файл modules.dep содержит строки вида:
$ cat /lib/modules/`uname -r`/modules.dep
...
misc/vboxnetadp.ko: misc/vboxdrv.ko
...
|
Каждая такая строка содержит:
- модули, от которых зависит данный модуль (например, модуль vboxnetadp зависим от единственного модуля uvboxdrv, но часто зависимости бывают от заметно большего числа модулей);
- полные пути к файлам всех модулей.
После этого загрузить модули не представляет труда, и непосредственно для этой работы вызывается (для каждого модуля последовательно) утилита insmod
. Команда depmod
(обновление дерева зависимости модулей) очень часто бывает завершающей командой в инсталляционных скриптах пакетов программного обеспечения, особенно тех, которые собирают и устанавливают собственные модули в систему.
Примечание: если загрузка модуля производится непосредственно утилитой insmod с указанием ей имени файла модуля, то утилита никакие зависимости не проверяет, а если обнаруживает неразрешённое имя, завершает загрузку аварийно.
Утилита rmmod
выгружает ранее загруженный модуль, в качестве параметра утилита должна получать имя модуля (но не имя файла модуля). Если в системе есть модули, зависимые от выгружаемого (счётчик ссылок использования модуля больше нуля), то выгрузка модуля не произойдёт, и утилита rmmod
завершится аварийно.
Совершенно естественно, что все утилиты insmod
, modprobe
, depmod
, rmmod
кардинально влияют на устойчивость системы, и поэтому для их запуска требуются полномочия root.
Инсталляция модуля
Инсталляция модуля, если необходимо обеспечить его постоянную загрузку при каждой загрузке операционной системы Linux, состоит из двух операций.
Во-первых, скопировать собранный модуль (*.ko) в его итоговое местоположение в иерархии модулей системы. Модули системы распределены по каталогам и чаще всего используется каталог misc:
$ ls -l /lib/modules/`uname -r` / grep ^d
drwxr-xr-x 2 root root 4096 Мар 16 2011 CiscoVPN
drwxr-xr-x 2 root root 4096 Мар 3 2010 extra
drwxr-xr-x 11 root root 4096 Мар 13 2010 kernel
drwxrwxr-x 2 root root 4096 Июн 25 12:47 misc
drwxr-xr-x 2 root root 4096 Мар 3 2010 updates
drwxr-xr-x 2 root root 4096 Мар 13 2010 vdso
drwxr-xr-x 2 root root 4096 Мар 3 2010 weak-updates
|
Во-вторых, обновить информацию о дереве зависимостей модулей (в связи с добавлением нового), что делается утилитой depmod
.
Если для инсталляции создается цель в Makefile, то нет ничего страшнее, чем пакеты, устанавливающие некоторые компоненты, но не умеющие их удалять! Лучше не иметь автоматической возможности инсталлировать модуль (выполняя эту задачу вручную), чем иметь установленный модуль, не имея возможности его деинсталлировать! Для удаления модуля, стационарно инсталлированного в системе, достаточно:
Во-первых, удалить файл модуля (*.ko) в каталоге его местоположения в иерархии модулей системы /lib/modules/`uname -r`:
$ ls -l /lib/modules/`uname -r` / grep ^d
|
Во-вторых, обновить информацию зависимостей модулей утилитой depmod
.
Заключение
В этой статье были рассмотрены общие вопросы загрузки модулей. Следующая статья будет посвящена параметрам, которые можно указывать при загрузке модуля, и передаче значений через эти параметры, и другие важные нюансы, связанные с управлением загрузкой модулей.