Очень хорошо изложено. На мой взгляд ещё стоит добавить про modprobe.d/*.conf — автоматическое конфигурирование модулей при загрузке. Полезно в частности для видео устройств.
Большое спасибо, очень доступный и информативный материал, однозначно в избранное.
Некоторые подробности загрузки/выгрузки стали более ясны и прозрачны
О да! По Роберту Лаву я учился писать модули ядра. Автор не только рассказывает как писать модули, но и передает некую философию, руководствуясь которой можно избежать многих ошибок проектирования и правильно программировать в условиях пространства ядра.
Ну извините конечно, но по этой статье можно с таким же успехом дать ссылку на man modprobe, man insmod, man lsmod, man rmmod, man modinfo и man modprobe.conf
> В Linux ядро монолитное, т.е. все его драйвера и подсистемы работают в своем адресном пространстве, отделенном от пользовательского.
Монолитное — значит что ядро не поделено на части, а не то что вы тут написали. Монолитное ядро противопоставляется микроядерным — Minix и HURD, где каждый отдельный сервис — это отдельный процесс а «истинное» микроядро лишь занимается обменом между информации между ними.
> rmmod
rmmod -> modprobe -r
> Эти зависимости просчитываются автоматически, и будут описаны ниже.
Я не совсем понял, что здесь значил слово «автоматически»?
А не одно и то же? Монолитное ядро по сути один большой процесс, выполняющийся в рамках одного адресного пространства. Все службы ядра существуют и выполняются в одном большом адресном пространстве ядра.
«Автоматически» — имелось ввиду, что не нужно все делать руками, есть специальные механизмы определения зависимостей и их разрешения.
Это не один процесс, это одно адресное пространство. Процессов много, но память общая и все могут друг-друга уронить или иметь общие данные без копирования.
Скрипты загрузки и выгрузки модулей, это, пока, единственный способ бороться с отваливанием вай-фая после суспенда или хибернейта. За статью спасибо, ее бы месяц назад.
зы. Регулярка find /lib/modules/`uname -r` -name ‘*.ko’ почему-то не срабатывает на убунту 10.10.
uname -r — это подстановка. Пишется в кавычках, которые находятся на русской букве «ё». А '*.ko' пишется в обычных одинарных кавычках. Подстановку можно, кстати, написать по другому:
find /lib/modules/$(uname -r) -name '*.ko'
>Необходимость в файле микропрограммы появилась в связи с тем, что интерфейс взаимодействия с устройством закрыт, и эти функции возложены на файл прошивки (firmware).
разве фирмварь не грузится в само устройство, а не драйвер?
обычно фирмваря — бинарный блоб, который драйвер читает из /lib/firmware/ и заливает в сустройство.
в этом конкретном — надо смотреть сорц. как-то странно было бы держать в памяти ядро непонятно что и не тэйнтить его, как в случае с проприетарными драйверами.
Большое спасибо за статью. Интересует такой вопрос — Есть ли смысл вкомпиливать модули в ядро, интересно узнать в каких случаях это может потребоваться и будет ли влиять на производительность или надежность?
Чем больше вкомпилено в ядро, тем ядро медленнее загружается (может и работает), но так безопаснее — вам не надо думать о том, что какой-то модуль мог не подгрузится, когда он нужен.
А если выбрать модульную структуру, то все наоборот)
Если что-то не вкомпилено в ядро, но нужно (критерий нужности с точки зрения автоматики) то это время, выигранное на этапе загрзуки ядра, будет скушано обратно на следующем этапе. Плюс уйдет время на подгрузку динамического объекта и всякие релокации.
Бывают ситуации, когда все нужные модули вкомпилируются в ядро и функция подгрузки модулей отключается. Это делают на тех системах, на которых не будут менять ни конфигурацию оборудования, ни файловые системы. Создается что-то типа бастиона, невозможно ничего не загрузить, ни выгрузить. Согласно этой политике повышается безопасность, т.к. невозможно загрузить какой либо вредоносный код в ядро. Но я с таким встречался только один раз, когда знакомый админ таким образом настроил внутренний шлюз. Он работал отлично, маршрутизировал довольно много трафика и держал аптаймы до нескольких лет. Но когда на маме сдохли конденсаторы и пришлось ее заменить — пришлось пересобирать ядро, т.к. таких матерей уже в продаже давно нет.
Смысл вкомпилировать только некоторые модули есть тогда, когда вы уверены, что это оборудование или файловая система будет у вас всегда, но опять же прироста в производительности это не даст. Я так поступаю чисто для удобства на домашней системе: вкомпилирую модули поддержки корневой файловой системы и контроллера жесткого диска в ядро, чтобы не использовать initrd. Других преимуществ я не вижу. Может быть кто нибудь еще просветит.
Согласен, я тоже этот метод не приемлю. Просто если цель нагадить в системе — да, этого достаточно, а чтобы незамеченно в системе сидела какая-то резидентная гадость — довольно не плохая идея интегрироваться в ядро.
Подсказали что плюс использовать модули невкомпиленными, в том что при обновлении модуля можно просто заменить модуль и нет необходимости пересобирать ядро. Сомневаюсь что такая ситуация может часто встречаться, тем более что модули часто зависят от версии ядра.
Я немного некорректно выразился, имел ввиду автозагрузку модуля при запуске системы. Например, чтобы грузится cryptoloop и blowfish на домашней генту я прописываю их в /etc/modules.autoload.d/kernel-2.6, а в тех же redhat системах механизм другой. Я подправлю вечером, спасибо.
А как ядро определяет, для какого устройства какой модуль грузить?
Есть устройство которое работает через COM-USB переходник (он внутри устройства стоит). Случайным образом при загрузке системы для устройства может быть загружен модуль pl2303 и соответственно оно станет /dev/ttyUSB*, а может загрузиться cdc_acm и оно станет /dev/ttyACM*
Внести один из этих модулей в blacklist я не могу, т.к. есть другие устройства, которые их используют. Как заставить ядро для USB устройства с конкретным ID грузить конкретный драйвер?
как-то очень странно — видимо устройство матчится под два разных драйвера и его ловит тот, который был загружен быстрее.
если действительно так, то похоже на баг и его надо бы отрепортить.
как воркарраунд, можно явно грузить один из модулей раньше, или прописать алиас.
еще можно разрулить на уровне имени устройства, написав хитрое правило udev.
А вот есть ли способ узнать, с какими опциями загружен модуль? Это, пожалуй, даже чаще востребовано, чем modinfo, особенно с ноутбуками с snd-hda-intel с их вечными проблемами с входом для наушников.
А также интересно, можно ли «на лету» изменить параметры загрузки модуля без его выгрузки (иногда зависимости не дают выгрузить) и повторной загрузки.
Если эти два вопроса имеют решение, хорошо было бы его увидеть в самой статье для полноты картины — к остальному содержимому претензий нет.
Довольно интересные вопросы… так чтобы списком получать я даже не знаю. Можно проверять значение параметра через файловую систему /sys: в каталоге "/sys/modules/<module_name>/parameters" сидят файлы, названные по имени параметра, данные в них — значения параметра.
А по поводу изменения параметров на лету никогда не сталкивался с проблемой, но поищу информацию. Спасибо за интересные вопросы.
Я всегда считал что некоторые вещи очень желательно делать модульными при сборке ядра, например — модуль wifi-карты и bluetooth. Все ради того, чтобы выгружать модуль ненужного в данный момент устройства и, типа, экономить электричество. Раскройте же глаза на правду, о линукс-гуру!)
Работаем с модулями ядра в Linux