Этот макрос не определяет переменную. Перед тем как использовать макрос, соответствующую переменную нужно определить. В связи с этим типичный пример использования может быть следующим.
/* параметр модуля, который управляет переменной 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.");
Вес описанные в этом разделе макросы требуют включения заголовочного файла .
При загрузке модули динамически компонуются с ядром. Так же как и в случае динамически загружаемых бинарных файлов пространства пользователя, в коде модулей могут вызываться только те функции ядра (основного образа или других модулей), которые явно экспортируются для использования. В ядре экспортирование осуществляется с помощью специальных директив EXPORT_SYMBOL()
и EXPORT_SYMBOL_GPL()
.
Функции, которые экспортируются, доступны для использования модулями. Функции, которые не экспортируются, не могут быть вызваны из модулей. Правила компоновки и вызова функций для модулей значительно более строгие, чем для основного образа ядра. Код ядра может использовать любые интерфейсы ядра (кроме тех, которые определены с ключевым словом static
), потому что код ядра компонуется в один выполняемый образ. Экспортируемые символы, конечно, тоже не должны определяться как static
.
Набор символов ядра, которые экспортируются, называется экспортируемым интерфейсом ядра или даже (здесь не нужно удивляться) API ядра .
Читать дальше