Выбрать главу

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, то экспортировать функцию можно следующим образом.