Библиотека сайта rus-linux.net
Цилюрик О.И. Модули ядра Linux | ||
Назад | Архитектура и вокруг... | Вперед |
Параметры загрузки модуля
Модулю при его загрузке могут быть переданы значения параметров — здесь наблюдается полная аналогия (по смыслу, но не по формату) с передачей параметров пользовательскому процессу из командной строки через массив argv[]. Такую передачу модулю параметров при его загрузке можно видеть в ближайшем рассматриваемом драйвере символьного устройства (архив cdev.tgz примеров). Более того, в этом модуле, если не указано явно значение параметра, то для него устанавливается его умалчиваемое значение (динамически определяемый системой старший номер устройства), а если параметр указан — то принудительно устанавливается заданное значение, даже если оно и недопустимо с точки зрения системы. Этот фрагмент выглядит так:
static int major = 0; module_param( major, int, S_IRUGO );
- определяется переменная параметр (с именем major), и далее это же имя указывается в макросе module_param(). Подобный макрос должен быть записан для каждого предусмотренного параметра, и должен последовательно определить: а). имя (параметра и переменной), б). тип значения, в). права доступа (к параметру, отображаемую как путевое имя в системе /sys.
Значения параметрам могут быть установлены во время загрузки модуля через insmod или modprobe ; последняя команда также можете прочитать значение параметра из своего файла конфигурации (/etc/modprobe.conf) для загрузки модулей.
Обработка входных параметров модуля обеспечивается макросами (описаны в <linux/moduleparam.h>), вот основные (там же есть ещё ряд мало употребляемых), два из них приводятся с полным определением через другие (что добавляет понимания):
module_param_named( name, value, type, perm ) #define module_param(name, type, perm) \ module_param_named(name, name, type, perm) module_param_string( name, string, len, perm ) module_param_array_named( name, array, type, nump, perm ) #define module_param_array( name, type, nump, perm ) \ module_param_array_named( name, name, type, nump, perm )
Но даже из этого подмножества употребляются чаще всего только два: module_param() и module_param_array() (детально понять работу макросов можно реально выполняя обсуждаемый ниже пример).
Примечание: Последним параметром perm указаны права доступа (например, S_IRUGO | S_IWUSR) к имени параметра, отображаемому в подсистеме /sys, если нас не интересует имя параметра отображаемое в /sys, то хорошим значением для параметра perm будет 0.
Для параметров модуля в макросе module_param() могут быть указаны следующие типы:
- bool, invbool - булева величина ( true или false) - связанная переменная должна быть типа int. Тип invbool инвертирует значение, так что значение true приходит как false и наоборот.
- charp - значение указателя на char - выделяется память для строки, заданной пользователем (не нужно предварительно распределять место для строки), и указатель устанавливается соответствующим образом.
- int, long, short, uint, ulong, ushort - базовые целые величины разной размерности; версии, начинающиеся с u, являются беззнаковыми величинами.
В качестве входного параметра может быть определён и массив выше перечисленных типов (макрос module_param_array()).
Пример, показывающий большинство приёмов использования параметров загрузки модуля (архив parms.tgz) показан ниже:
mod_params.c :
#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/string.h> MODULE_LICENSE( "GPL" ); MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" ); static int iparam = 0; module_param( iparam, int, 0 ); static int k = 0; // имена параметра и переменной различаются module_param_named( nparam, k, int, 0 ); static char* sparam = ""; module_param( sparam, charp, 0 ); #define FIXLEN 5 static char s[ FIXLEN ] = ""; // имена параметра и переменной различаются module_param_string( cparam, s, sizeof( s ), 0 ); static int aparam[] = { 0, 0, 0, 0, 0 }; static int arnum = sizeof( aparam ) / sizeof( aparam[ 0 ] ); module_param_array( aparam, int, &arnum, S_IRUGO | S_IWUSR ); static int __init mod_init( void ) { int j; char msg[ 40 ] = ""; printk( KERN_INFO "========================================\n" ); printk( KERN_INFO "iparam = %d\n", iparam ); printk( KERN_INFO "nparam = %d\n", k ); printk( KERN_INFO "sparam = %s\n", sparam ); printk( KERN_INFO "cparam = %s {%d}\n", s, strlen( s ) ); sprintf( msg, "aparam [ %d ] = ", arnum ); for( j = 0; j < arnum; j++ ) sprintf( msg + strlen( msg ), " %d ", aparam[ j ] ); printk( KERN_INFO "%s\n========================================\n", msg ); return -1; } module_init( mod_init );
Для сравнения - выполнение загрузки модуля с параметрами по умолчанию, а затем с переопределением значений всех параметров:
$ sudo /sbin/insmod ./mod_params.ko
insmod: error inserting './mod_params.ko': -1 Operation not permitted
$ dmesg | tail -n7
======================================== iparam = 0 nparam = 0 sparam = cparam = {0} aparam [ 5 ] = 0 0 0 0 0 ========================================
$ sudo /sbin/insmod ./mod_params.ko iparam=3 nparam=4 sparam=str1 \
cparam=str2 aparam=5,4,3
insmod: error inserting './mod_params.ko': -1 Operation not permitted $ dmesg | tail -n7 ======================================== iparam = 3 nparam = 4 sparam = str1 cparam = str2 {4} aparam [ 3 ] = 5 4 3 ========================================
- массив aparam получил новую размерность arnum, и присвоены значения его элементам.
Вводимые параметры загрузки и их значения в команде insmod жесточайшим образом контролируются (хотя, естественно, всё проконтролировать абсолютно невозможно), потому как модуль, загруженный с ошибочными значениями параметров, который становится составной частью ядра — это угроза целостности системы. Если хотя бы один из параметров признан некорректным, загрузка модуля не производится. Вот как происходит контроль для некоторых случаев:
$ sudo /sbin/insmod ./mod_params.ko aparam=5,4,3,2,1,0
insmod: error inserting './mod_params.ko': -1 Invalid parameters
$ dmesg | tail -n2
aparam: can only take 5 arguments mod_params: `5' invalid for parameter `aparam'
- имела место попытка заполнить в массиве aparam число элементов большее, чем его зарезервированная размерность (5).
$ sudo /sbin/insmod ./mod_params.ko zparam=3
insmod: error inserting './mod_params.ko': -1 Unknown symbol in module
$ dmesg | tail -n1
mod_params: Unknown parameter `zparam'
- не определённый в модуле параметр.
$ sudo /sbin/insmod ./mod_params.ko iparam=qwerty
insmod: error inserting './mod_params.ko': -1 Invalid parameters
$ dmesg | tail -n1
mod_params: `qwerty' invalid for parameter `iparam'
- попытка присвоения не числового значения числовому типу.
$ sudo /sbin/insmod ./mod_params.ko cparam=123456789
insmod: error inserting './mod_params.ko': -1 No space left on device
$ dmesg | tail -n2
cparam: string doesn't fit in 4 chars. mod_params: `123456789' too large for parameter `cparam'
- превышена максимальная длина для строки, передаваемой копированием.
Предыдущий раздел: | Оглавление | Следующий раздел: |
Загрузка модулей | Подсчёт ссылок использования |