Other Alias
init_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 экспортировал 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, указывают в тело модуля и будут инициализированы в соответствии с адресным пространством ядра, то есть перемещены с остальной частью модуля.