Lsmod — unix, linux command

Подробности загрузки модуля

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

Рисунок 4. Внутренний процесс загрузки модуля (упрощенно)

Внутренние процессы загрузки модуля представляют собой анализ и управление модулями ELF. Функция (которая находится в ./linux/kernel/module.c) начинает с выделения блока временной памяти для хранения всего модуля ELF. Затем модуль ELF считывается из пользовательского пространства во временную память при помощи
. Являясь объектом ELF, этот файл имеет очень специфичную структуру, которая легко поддается анализу и проверке.

Следующим шагом является ряд «санитарных проверок» загруженного образа (является ли ELF-файл допустимым? соответствует ли он текущей архитектуре? и так далее). После того как проверка пройдена, образ ELF анализируется и создается набор вспомогательных переменных для заголовка каждого раздела, чтобы облегчить дальнейший доступ к ним. Поскольку базовый адрес объектного файла ELF равен 0 (до перемещения), эти переменные включают соответствующие смещения в блок временной памяти. Во время создания вспомогательных переменных также проверяются заголовки разделов ELF, чтобы убедиться, что загружаемый модуль корректен.

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

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

Затем производится проход по оставшимся разделам и выполняются перемещения. Этот шаг зависит от архитектуры и соответственно основывается на вспомогательных функциях, определенных для данной архитектуры (./linux/arch/<arch>/kernel/module.c). В конце очищается кэш инструкций (поскольку использовались временные разделы .text), выполняется еще несколько служебных процедур (очистка памяти временного модуля, настройка sysfs) и, в итоге, модуль возвращает
.

Safe Mode

If the effective uid is not equal to the real uid, then modprobe treats its input with extreme suspicion. The last parameter is always treated as a module name, even if it starts with -. There can only be one module name and options of the form variable=value are forbidden. The module name is always treated as a string, no meta expansion is performed in safe mode. However, meta expansion is applied to data read from the config file.

euid may not be equal to uid when modprobe is invoked from the kernel, this is true for kernels 2.4.0-test11 and later. In an ideal world, modprobe could trust the kernel to only pass valid parameters to modprobe. However, at least one local root exploit has occurred because high-level kernel code passed unverified parameters direct from the user to modprobe. So modprobe no longer trusts kernel input.

modprobe automatically sets safe mode when the environment consists only of these strings

HOME=/ TERM=linux PATH=/sbin:/usr/sbin:/bin:/usr/bin

This detects modprobe execution from the kernel on kernels 2.2 though 2.4.0-test11, even if uid == euid, which it does on the earlier kernels.

Запрет загрузки

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

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

С помощью файлов в /etc/modprobe.d/

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

/etc/modprobe.d/nobeep.conf
# Do not load the 'pcspkr' module on boot.
blacklist pcspkr

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

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

/etc/modprobe.d/blacklist.conf
...
install module_name /bin/false
...

Это запретит данный модуль и все модули, зависящие от него.

С помощью командной строки ядра

Совет: Это может очень помочь, если неправильный модуль не даёт загрузиться вашей системе.

Вы также можете запрещать модули из загрузчика.

Просто добавьте в вашем загрузчике в строку ядра, как описано в параметрах ядра.

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

Подробности выгрузки модуля

Выгрузка модуля фактически представляет собой зеркальное отражение процесса загрузки за исключением того, что для безопасного удаления модуля необходимо выполнить несколько «санитарных проверок». Выгрузка модуля начинается в пользовательском пространстве с выполнения команды
(удалить модуль). Внутри команды
выполняется системный вызов
, который в конечном счете инициирует внутри ядра (вернитесь к ). Основные операции удаления модуля показаны на рисунке 5.

Рисунок 5. Внутренний процесс выгрузки модуля (упрощенно).

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

К моменту вызова уже известно, что модуль может быть безопасно удален. Зависимостей не обнаружено, и для данного модуля можно начать процесс очистки ядра. Этот процесс начинается с удаления модуля из различных списков, в которые он был помещен во время установки (sysfs, список модулей и т.д.). Потом инициируется команда очистки, зависящая от архитектуры (она расположена в ./linux/arch/<arch>/kernel/module.c). Затем обрабатываются зависимые модули, и данный модуль удаляется из их списков. В конце, когда с точки зрения ядра очистка завершена, освобождаются различные области памяти, выделенные для модуля, в том числе память для параметров, память для данных по процессорам и память модуля ELF ( и
).

Настройка Grub через /boot/grub/grub.cfg

Файл /etc/boot/grub/grub.cfg управляет непосредственно работой загрузчика, здесь указаны все его параметры и настройки, а также сформировано меню. Поэтому, изменяя этот файл, мы можем настроить Grub как угодно. Сначала попытаемся разобраться с синтаксисом файла. Он очень напоминает синтаксис bash и состоит из нескольких команд, которые что-то делают, загружают и настраивают.

Команды могут быть объединены в функции или блоки с помощью инструкций if else, синтаксис которых аналогичен bash. Рассмотрим основные из этих команд:

  • load_env — загрузить переменные окружения из файла;
  • set — установить значение переменной окружения. Используется как set имя_переменной=значение;
  • insmod — загрузить модуль из папки с модулями Grub;
  • linux — загружает ядро Linux;
  • initrd — подготавливает образ initrd для загрузки ядра;
  • boot — пытается загрузить систему;
  • chainloader — запускает загрузчик из другого раздела;
  • search — установить значение переменной выполнив поиск по заданным параметрам, например, может найти диск по его UUID или метке;
  • menuentry — позволяет создать пункт меню;

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

Команда search используется для поиска дисков и имеет такой синтаксис:

$ search опции_поиска —set=имя_переменной —hint приметы_устройства основной_параметр

  • Опции поиска задают по какому критерию нужно искать, например, —fs-uuid — искать по UUID, —label — по метке, —no-floppy — не искать в схемных носителях.
  • Приметы устройства дают программе дополнительные подсказки для более быстрого поиска;
  • Основной параметр — значение, по которому будем выполнять поиск.

Например, команда может выглядеть вот так:

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

menuentry имя_пункта {команды установки переменных окружениязагрузка модулейlinux файл_ядра параметры_ядраinitrd файл_initrd}

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

Теперь давайте попробуем собрать всю информацию воедино и создадим самый просто конфигурационный файл для Grub вручную:

# Время показа меню 5 секунд

set timeout=5

# Установим разрешение экрана и укажем что это же разрешение нужно сохранять для ядра:

set gfxmode=»1280×800″
set gfxpayload=keep

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

insmod vbe
insmod gfxterm
terminal_output gfxterm

# Установка шрифта с поддержкой Unicode:

font «/boot/grub2/fonts/unicode.pf2»
loadfont unicode

# Загрузим модуль работы с jpeg и зададим фоновый рисунок:

insmod jpeg
background_image «/boot/fon.jpg»

# Установим переменные окружения для настройки цвета меню:

set menu_color_normal=red/black
set menu_color_highlight=yellow/black
set color_normal=yellow/black

menuentry «Ubuntu» {
root=(hd0,1)
linux /casper/vmlinuz boot=casper noeject noprompt splash
initrd /casper/initrd.lz
}

menuentry «OpenSUSE» {
insmod gzio
insmod part_msdos
insmod ext2
set root=’hd0,msdos5′
linux /boot/vmlinuz-4.1.31-30-default root=UUID=c52ca066-e48f-4df2-bc7e-4d885a354090 resume=/dev/sda7 splash=silent quiet showopts
initrd /boot/initrd-4.1.31-30-default
}

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

Программа настройки Grub — это хорошо, но также важно понимать как все работает на низком уровне

Description of the Command

The modprobe and depmod utilities are intended to make a Linux modular kernel more manageable for users, administrators, and distribution maintainers.

Modprobe uses a Makefile-like dependency file, created by depmod, to automatically load the relevant modules from the set of modules available in predefined directory trees.

Modprobe is used to load a single module, a stack of dependent modules, or all modules that are marked with a specified tag.

Modprobe automatically loads all base modules needed in a module stack, as described by the dependency file modules.dep. If the loading of one of these modules fails, the whole current stack of modules loaded in the current session are unloaded automatically.

Modprobe has two ways of loading modules. One way (the probe mode) will try to load a module out of a list (defined by pattern). Modprobe stops loading as soon as one module loads successfully. This could be used to autoload one Ethernet driver out of a list. The other way modprobe can be used is to load all modules from a list.

With the option -r, modprobe automatically unloads a stack of modules, similar to the way rmmod -r does. Using only modprobe -r cleans up unused autoloaded modules and also performs the pre- and post-remove commands in the configuration file /etc/modules.conf.

Combining the options -l and -t lists all available modules of a certain type.

Option -c prints the currently used configuration (default + configuration file).

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

Ранее неоднократно показывалось, как использовать команду для загрузки только что собранных модулей. Но это был самый низкий уровень модульной подсистемы, так как вряд ли пользователь удовлетворится необходимостью поштучной загрузки всех модулей при каждой загрузке операционной системы Linux, да ещё и с необходимостью указания полного путевого имени каждого загружаемого модуля. С другой стороны, некоторая интегрированная среда, производящая загрузку всех необходимых модулей при загрузке системы, тоже представляла бы определённую проблему. Так, если загрузить один раз модуль (например, в порядке тестирования), который делает невозможной дальнейшую загрузку системы (терминальная ошибка), то эта ситуация воспроизводилась при каждой загрузке системы (для исправления ошибки загрузки нужна работающая система и редактор конфигураций, но для загрузки системы нужна исправленная конфигурация — получается порочный замкнутый круг). Для разрешения этой коллизии в системе оставлены два альтернативных способа загрузки модулей: команда и команда .

Утилита получает имя файла модуля (с указанием полного путевого имени, если это необходимо, и расширения имени файла .ko) и пытается загрузить его без каких-либо проверок взаимосвязей, как отдельный автономный файл: либо он загружается, либо нет. Утилита modprobe работает более тонко: ей передаётся или универсальный идентификатор, или непосредственное имя модуля. Если modprobe получает универсальный идентификатор, то она сначала пытается найти соответствующее имя модуля в файле /etc/modprobe.conf (устаревшее поведение), или в любом из файлов *.conf в каталоге /etc/modprobe.d, где каждому универсальному идентификатору поставлено в соответствие имя файла модуля (записанное в строке , см. ).

Далее утилита modprobe по имени модуля и по содержимому файла зависимостей /lib/modules/`uname -r`/modules.dep пытается установить зависимости запрошенного модуля: модули, от которых зависит запрошенный модуль, будут загружены до него самого. Понятно, что это рекурсивный процесс, и он будет продолжаться до тех пор, пока все зависимости не будут разрешены или не будет найдена зависимость от неизвестного модуля и, тем самым, установлена невозможность загрузки всей иерархии зависимых модулей, и как конечный итог загрузки запрошенного модуля, т.е. попытка оказывается неудачной.

Файл зависимостей modules.dep заранее формируется командой:

# depmod -a

Этой же командой (время от времени) обновляется и большинство других файлов 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 с указанием ей имени файла модуля, то утилита никакие зависимости не проверяет, а если обнаруживает неразрешённое имя, завершает загрузку аварийно.

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

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

Obtaining information

Modules are stored in . You can use the command to get your current kernel release version.

Note: Module names often use underscores () or dashes (); however, those symbols are interchangeable when using the command and in configuration files in .

To show what kernel modules are currently loaded:

$ lsmod

To show information about a module:

$ modinfo module_name

To list the options that are set for a loaded module:

$ systool -v -m module_name

To display the comprehensive configuration of all the modules:

$ modprobe -c | less

To display the configuration of a particular module:

$ modprobe -c | grep module_name

List the dependencies of a module (or alias), including the module itself:

$ modprobe --show-depends module_name

Description

Modules are pieces of code which extend the functionality of the operating system kernel without the need to reboot. Once loaded, modules reside in memory, and can be instantiated multiple times; they can be thought of as analogous to a device driver.

modprobe uses the dependency lists and hardware maps generated by depmod to intelligently load or unload modules into the kernel. It performs the actual insertion and removal using the lower-level programs insmod and rmmod, respectively.

While it’s possible to call insmod and rmmod manually, it’s recommended to load and unload modules using depmod to ensure that any inter-module dependencies are considered before changes are made.

Troubleshooting

Extracting the image

If you are curious about what is inside the initrd image, you can extract it and poke at the files inside of it.

The initrd image is an SVR4 CPIO archive, generated via the and commands, optionally compressed with a compression scheme understood by the kernel. For more information on the compression schemes, see .

mkinitcpio includes a utility called which will list and extract the contents of initramfs images.

You can list the files in the image with:

$ lsinitcpio /boot/initramfs-linux.img

And to extract them all in the current directory:

$ lsinitcpio -x /boot/initramfs-linux.img

You can also get a more human-friendly listing of the important parts in the image:

$ lsinitcpio -a /boot/initramfs-linux.img

Recompressing a modified extracted image

After extracting an image as explained above, after modifying it, you can find the command necessary to recompress it. Edit and change the line as shown below (line 531 in mkinitcpio v20-1.)

#MKINITCPIO_PROCESS_PRESET=1 "$0" "${preset_cmd}"
MKINITCPIO_PROCESS_PRESET=1 /usr/bin/bash -x "$0" "${preset_cmd}"

Then running with its usual options (typically ), toward the last 20 lines or so you will see something like:

+ find -mindepth 1 -printf '%P\0'
+ LANG=C
+ bsdcpio -0 -o -H newc --quiet
+ gzip

Which corresponds to the command you need to run, which may be:

# find -mindepth 1 -printf '%P\0' | LANG=C bsdcpio -0 -o -H newc --quiet | gzip > /boot/initramfs-linux.img

Warning: It is a good idea to rename the automatically generated /boot/initramfs-linux.img before you overwrite it, so you can easily undo your changes. Be prepared for making a mistake that prevents your system from booting. If this happens, you will need to boot through the fallback, or a boot CD, to restore your original, run mkinitcpio to overwrite your changes, or fix them yourself and recompress the image.

«/dev must be mounted» when it already is

The test used by mkinitcpio to determine if /dev is mounted is to see if /dev/fd/ is there. If everything else looks fine, it can be «created» manually by:

# ln -s /proc/self/fd /dev/

(Obviously, /proc must be mounted as well. mkinitcpio requires that anyway, and that is the next thing it will check.)

Possibly missing firmware for module XXXX

When initramfs are being rebuild after a kernel update, you might get these two warnings:

==> WARNING: Possibly missing firmware for module: aic94xx
==> WARNING: Possibly missing firmware for module: smsmdtv 

These appear to any Arch Linux users, especially those who have not installed these firmware modules. If you do not use hardware which uses these firmwares you can safely ignore this message.

mkinitcpio creates images with all the shared libraries missing

If your machine fails to boot with an «Attempted to kill init!» kernel panic right off the bat (before any or -related messages appear on the screen), and running reveals that all the shared libraries are missing from the images generated in , make sure there is a symbolic link at pointing to , and rebuild them all.

Загрузка выполняется на одной машине и терпит неудачу на другой

hook скрипта mkinitcpio фильтрует ненужные kernel modules в первичном initramfs путем сканирования /sys и модулей, загруженных во время запуска. Если вы переносите /boot каталог на другую машину и последовательность загрузки терпит неудачу на стадии early userspace, то это может проиходить, потому что новое аппаратное обеспечение не определено отсутствующими модулями ядра

Обратите внимание, что для USB 2.0 и 3.0 нужны разные модули ядра

Чтобы исправить, сначала попробуйтей выбрать fallback образ в вашем загрузчике, поскольку он не фильтруется с помощью . После загрузки выполните mkinitcpio на новой машине, чтобы пересобрать первичный образ с корректными модулями. Если fallback образ не решил проблему, пропробуйте загрузиться в Arch Linux live CD/USB, выполнить chroot в установленную систему и выполнить mkinitcpio на новой машине. В крайнем случае, попробуйте добавить модули в initramfs.

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

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

Adblock
detector