Книга: Разработка ядра Linux
Параметры модулей
Параметры модулей
Ядро Linux предоставляет возможность драйверам определять параметры, которые пользователь будет указывать при загрузке ядра или модуля. Эти параметры будут доступны коду модуля в качестве глобальных переменных. Указанные параметры модулей также будут отображаться в файловой системе sysfs (см. главу 17, "Объекты kobject и файловая система sysfs"). Определять параметры модуля и управлять ими просто.
Параметр модуля определяется с помощью макроса module_param()
следующим образом.
module_param(name, type, perm);
где аргумент name
— это имя неременной, которая появляется в модуле, и имя параметра, который может указать пользователь. Аргумент type
— это тип данных параметра. Значения типа могут быть следующими: byte
, short
, ushort
, int
, uint
, long
, ulong
, charp
, bool
или invbool
. Эти значения соответствуют следующим типам данных: байт; короткое целое число; короткое целое число без знака; целое число; целое число без знака; длинное целое; длинное целое число без знака; указатель на строку символов; булев тип; булев тип, значение которого инвертируется по сравнению с тем, которое указывает пользователь. Данные типа byte
хранятся в переменной типа char
, а данные булевых типов — в переменных типа int
. Остальные- типы соответствуют аналогичным типам языка С. Наконец, аргумент perm
указывает права доступа к соответствующему файлу в файловой системе sysfs. Права доступа можно указать как в обычном восьмеричном формате, например 0644 (владелец имеет права на чтение и запись, группа имеет права на чтение и запись, остальные пользователи имеют право только на чтение), так и в виде определений препроцессора, объединенных с помощью оператора "|
", например S_IRUGO | S_IWUSR
(все могут считывать данные, а владелец также и записывать). Нулевое значение этого параметра приводит к тому, что соответствующий файл в файловой системе sysfs не появляется.
Этот макрос не определяет переменную. Перед тем как использовать макрос, соответствующую переменную нужно определить. В связи с этим типичный пример использования может быть следующим.
/* параметр модуля, который управляет переменной bait */
static int allow live bait = 1; /* по умолчанию включено */
module_param(allow_live_bait, bool, 0644); /* булев тип */
Это определение должно быть в глобальной области видимости, т.е. неременная allow_live_bait
должна быть глобальной.
Существует возможность дать внешнему параметру модуля имя, отличное от имени переменной. Это можно сделать с помощью макроса module_param_named()
.
module_param_named(name, variable, type, perm);
где name
— это имя внешнего параметра модуля, a variable
— имя внутренней глобальной переменной модуля, как показано ниже.
static unsigned int max_test = DEFAULT_МАХ_LINE_TEST;
module_param_named(maximum_line_test, max_test, int, 0);
Для того чтобы определить параметр модуля, значением которого является строка символов, необходимо использовать тип charp
. Ядро копирует переданную пользователем строку символов в память и присваивает переменной указатель на эту строку, как в следующем примере.
static char *name;
module_param(name, charp, 0);
При необходимости ядро может скопировать строку в заранее определенный массив символов, который указывает разработчик. Это делается с помощью макроса module_param_string()
.
module_param_string(name, string, len, perm);
где name
— это имя внешнего параметра, string
— имя внутренней переменной, которая содержит указатель на область памяти массива, len
— размер буфера string
(или некоторое меньшее число, чем размер буфера, что, однако, обычно не имеет смысла), perm
— права доступа к файлу на файловой системе sysfs (нулевое значение запрещает доступ к параметру через sysfs). Пример показан ниже.
static char species[BUF_LEN];
module_param_string(specifies, species, BUF_LEN, 0);
В качестве параметров модуля также можно передавать список значений, которые разделены запятой и в коде модуля будут записаны в массив данных. Эти параметры модуля можно обработать с помощью макроса module_param_array() следующим образом.
module_param_array(name, type, nump, perm);
В данном случае аргумент name
— это имя внешнего параметра и внутренней переменной, type
— это тип данных одного значения, a perm — это права доступа к файлу на файловой системе sysfs. Новый аргумент nump
— это указатель на целочисленное значение, где ядро сохраняет количество элементов, записанных в массив. Обратите внимание, что массив, который передается в качестве параметра name, должен быть выделен статически. Ядро определяет размер массива на этапе компиляции и гарантирует, что он не будет переполнен. Как использовать данный макрос, показано в следующем примере.
static int fish[MAX_FISH];
static int nr_fish;
module_param_array(fish, int, &nr_fish, 0444);
Внутренний массив может иметь имя, отличное от имени внешнего параметра, в этом случае следует использовать макрос module_param_array_named()
.
module_param_array_named(name, array, type, nump, perm);
Параметры идентичны аналогичным параметрам других макросов.
Наконец, параметры модуля можно документировать, используя макрос MODULE_PARM_DESC()
.
static unsigned short size = 1;
module_param(size, ushort, 0644);
MODULE_PARM_DESC(size, "The size in inches of the fishing pole "
"connected to this computer.");
Вес описанные в этом разделе макросы требуют включения заголовочного файла <linux/moduleparam.h>
.