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>
.
Экспортируемые символы
При загрузке модули динамически компонуются с ядром. Так же как и в случае динамически загружаемых бинарных файлов пространства пользователя, в коде модулей могут вызываться только те функции ядра (основного образа или других модулей), которые явно экспортируются для использования. В ядре экспортирование осуществляется с помощью специальных директив EXPORT_SYMBOL()
и EXPORT_SYMBOL_GPL()
.
Функции, которые экспортируются, доступны для использования модулями. Функции, которые не экспортируются, не могут быть вызваны из модулей. Правила компоновки и вызова функций для модулей значительно более строгие, чем для основного образа ядра. Код ядра может использовать любые интерфейсы ядра (кроме тех, которые определены с ключевым словом static
), потому что код ядра компонуется в один выполняемый образ. Экспортируемые символы, конечно, тоже не должны определяться как static
.
Набор символов ядра, которые экспортируются, называется экспортируемым интерфейсом ядра или даже (здесь не нужно удивляться) API ядра.
Экспортировать символы просто. После того как функция определена, необходимо вызвать директиву EXPORT_SYMBOL()
.
/*
* get_pirate_beard_color — возвратить значение цвета бороды текущего
* пирата pirate — это глобальная переменная, доступная из данной
* функции цвета определены в файле <linux/beard_colors.h>
*/
int get_pirate_beard_color(void) {
return pirate->beard->color;
}
EXPORT_SYMBOL(get_pirate_beard_color);
Допустим, что функция get_pirate_beard_color()
объявлена в заголовочном файле и ее может использовать любой модуль.
Некоторые разработчики хотят, чтобы их интерфейсы были доступны только для модулей с лицензией GPL. Такая возможность обеспечивается компоновщиком ядра с помощью макроса MODULE_LICENSE()
. Если есть желание, чтобы рассматриваемая функция была доступна только для модулей, которые помеченные как соответствующие лицензии GPL, то экспортировать функцию можно следующим образом.