- bullseye-backports 4.18.1-1~bpo11+1
- testing 4.18.1-1
- unstable 4.18.1-1
INIT_MODULE(2) | Руководство программиста Linux | INIT_MODULE(2) |
ИМЯ¶
init_module, finit_module - загружает модуль ядра
СИНТАКСИС¶
int init_module(void *module_image, unsigned long len, const char *param_values);
int finit_module(int fd, const char *param_values, int flags);
Замечание: В заголовочных файлах glibc отсутствует init_module() и finit_module(); смотрите ЗАМЕЧАНИЯ.
ОПИСАНИЕ¶
Вызов init_module() загружает образ ELF в пространство ядра, выполняет все необходимые перемещения символов, инициализирует значения параметров модуля, предоставленные вызывающим и запускает функцию модуля init. Данный системный вызов требует дополнительных прав.
Аргумент module_image указывает на буфер, содержащий двоичный образ для загрузки; в len задаётся размер этого буфера. Образ модуля должен быть корректным образом в формате ELF, собранным для работающего в данный момент ядра.
Значением param_values является строка, содержащая значения параметров модуля (через пробел), определённых в модуле через module_param() и module_param_array(). Ядро обрабатывает эту строку и инициализирует указанные параметры. Каждый параметр имеет вид:
имя[=значение[,значение…]]
Параметр имя — один из определённых параметров модуля с помощью module_param() (смотрите файл исходного кода ядра Linux include/linux/moduleparam.h). Параметр значение не обязателен в случае параметров с типом bool и invbool. Значение массива параметров указываются через запятую.
finit_module()¶
Системный вызов finit_module() подобен init_module(), но читает модуль для загрузки из файлового дескриптора fd. Он полезен, если подлинность модуля ядра можно определить по его расположению в файловой системе; в таких случаях затрат на использование криптографически подписанных модулей для определения подлинности модуля можно избежать. Аргумент param_values такой же как у init_module().
Аргумент flags изменяет выполнение finit_module(). Это битовая маска, создаваемая объединением нуля или более следующих флагов:
- MODULE_INIT_IGNORE_MODVERSIONS
- Игнорировать хэши версий символов.
- MODULE_INIT_IGNORE_VERMAGIC
- Игнорировать версию ядра.
Есть несколько элементов, встроенных в модуль, которые позволяют убедиться, что модуль подходит для загрузки в ядро. Эти элементы записываются в модуль на этапе сборки и проверяются при загрузке ядра. Во-первых, модуль имеет строку «vermagic», содержащую номер версии ядра и основные свойства (такие как тип ЦП). Во-вторых, если модуль собран с включённым параметром настройки CONFIG_MODVERSIONS, то он содержит хэш версии для каждого используемого модулем символа. Данный хэш основан на типе аргумента и возвращаемом значении функции с именем символа. В этом случае номер версии ядра в строке «vermagic» игнорируется, так как считается, что хэши версий символов достаточно надёжны.
Использование флага MODULE_INIT_IGNORE_VERMAGIC требует игнорировать строку «vermagic», а флаг MODULE_INIT_IGNORE_MODVERSIONS требует игнорировать хэши версий символов. Если ядро собрано с разрешением принудительной загрузки (параметр настройки CONFIG_MODULE_FORCE_LOAD), то загрузка продолжается, в противном случае она завершается ошибкой ENOEXEC, как и ожидается для некорректных модулей.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
ОШИБКИ¶
- EBADMSG (начиная с Linux 3.7)
- Неправильный формат подписи модуля.
- EBUSY
- Истекло время ожидания попытки определения символьной ссылки данным модулем.
- EFAULT
- Аргумент адреса ссылается на положение вне доступного адресного пространства процесса.
- ENOKEY (начиная с Linux 3.7)
- Некорректная подпись или ядро не содержит ключа этого модуля. Данная ошибка возвращается только, если ядро было настроено с параметром CONFIG_MODULE_SIG_FORCE; если ядро собрано без этого параметра, то некорректный или не подписанный модуль просто примешивается (taints) в ядро.
- ENOMEM
- Не хватает памяти.
- EPERM
- Вызывающий не имеет прав (не имеет мандата CAP_SYS_MODULE), или отключена загрузка модулей (смотрите /proc/sys/kernel/modules_disabled в proc(5)).
Дополнительно в init_module() могут возникать следующие ошибки:
- EEXIST
- Модуль с таким именем уже загружен.
- EINVAL
- Некорректное значение param_values, или какая-то часть образа ELF в module_image содержит противоречивую информацию.
- ENOEXEC
- Двоичный образ, переданный module_image, не является образом ELF, или образ ELF некорректный или для другой архитектуры.
Дополнительно в finit_module() могут возникать следующие ошибки:
- EBADF
- Файл, на который ссылается fd, не открыт для чтения.
- EFBIG
- Файл, на который ссылается fd, слишком большой.
- EINVAL
- Значение flags неверно.
- ENOEXEC
- Значение fd не указывает на открытый файл.
Дополнительно к этим ошибкам, если функция модуля init при выполнении возвратила ошибку, то init_module() или finit_module() завершается с ошибкой и в errno записывается значение, полученное от функции init.
ВЕРСИИ¶
Вызовы finit_module() доступен в Linux, начиная с версии 3.8.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Вызовы init_module() и finit_module() есть только в Linux.
ЗАМЕЧАНИЯ¶
Системный вызов init_module() не поддерживается glibc. В заголовочных файлах glibc он не объявлен, но в недавнем прошлом glibc до версии 2.23 экспортировал ABI для этого системного вызова. Поэтому чтобы получить данный системный вызов достаточно вручную объявить интерфейс в своём коде; или же вы можете вызвать его через syscall(2).
В glibc нет обёртки для finit_module(); запускайте его с помощью syscall(2).
Информацию по уже загруженным модулями можно найти в файле /proc/modules и в соответствующем каждому модулю подкаталогу в /sys/module.
Дополнительную информацию смотрите в файле include/linux/module.h из исходного кода ядра Linux.
Linux версии 2.4 и более ранние¶
В Linux версии 2.4 и более ранних системный вызов init_module() был немного другим:
#include <linux/module.h>
int init_module(const char *name, struct module *image);
(Приложения пользовательского пространства могут определить какая из версий init_module() доступна, вызвав query_module(); этот вызов завершается ошибкой ENOSYS в Linux 2.6 и более новых.)
Старая версия системного вызова загружает перемещённый образ модуля image, в пространство ядра и выполняет функцию модуля init. Вызывающий должен предоставить перемещённый образ (начиная с Linux 2.6, системный вызов init_module() сам делает перемещение).
Образ модуля начинается со структуры модуля, за которой следует код и данные. Начиная с Linux 2.2 структура модуля определена следующим образом:
struct module {
unsigned long size_of_struct;
struct module *next;
const char *name;
unsigned long size;
long usecount;
unsigned long flags;
unsigned int nsyms;
unsigned int ndeps;
struct module_symbol *syms;
struct module_ref *deps;
struct module_ref *refs;
int (*init)(void);
void (*cleanup)(void);
const struct exception_table_entry *ex_table_start;
const struct exception_table_entry *ex_table_end; #ifdef __alpha__
unsigned long gp; #endif };
Все поля указателей, за исключением next и refs, указывают в тело модуля и будут инициализированы в соответствии с адресным пространством ядра, то есть перемещены с остальной частью модуля.
СМ. ТАКЖЕ¶
create_module(2), delete_module(2), query_module(2), lsmod(8), modprobe(8)
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
15 сентября 2017 г. | Linux |