Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра 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' 

- превышена максимальная длина для строки, передаваемой копированием.


Предыдущий раздел: Оглавление Следующий раздел:
Загрузка модулей   Подсчёт ссылок использования