Внутренний массив может иметь имя, отличное от имени внешнего параметра, в этом случае следует использовать макрос 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
.
Набор символов ядра, которые экспортируются, называется экспортируемым интерфейсом ядра или даже (здесь не нужно удивляться)
Экспортировать символы просто. После того как функция определена, необходимо вызвать директиву EXPORT_SYMBOL()
.
/*
* get_pirate_beard_color — возвратить значение цвета бороды текущего
* пирата pirate — это глобальная переменная, доступная из данной
* функции цвета определены в файле
*/
int get_pirate_beard_color(void) {
return pirate->beard->color;
}
EXPORT_SYMBOL(get_pirate_beard_color);
Допустим, что функция get_pirate_beard_color()
объявлена в заголовочном файле и ее может использовать любой модуль.
Некоторые разработчики хотят, чтобы их интерфейсы были доступны только для модулей с лицензией GPL. Такая возможность обеспечивается компоновщиком ядра с помощью макроса MODULE_LICENSE()
. Если есть желание, чтобы рассматриваемая функция была доступна только для модулей, которые помеченные как соответствующие лицензии GPL, то экспортировать функцию можно следующим образом.
EXPORT_SYMBOL_GPL(get_pirate_beard_color);
Если код ядра конфигурируется для компиляции в виде модуля, то необходимо гарантировать, что все используемые интерфейсы экспортируются. В противном случае будут возникать ошибки компоновщика и загружаемый модуль не будет работать.
Вокруг модулей
В этой главе были рассмотрены особенности написания, сборки, загрузки и выгрузки модулей ядра. Мы обсудили, что такое модули и каким образом ядро операционной системы Linux, несмотря на то что оно является монолитным, может загружать код динамически. Были также рассмотрены параметры модулей и экспортируемые символы. На примере воображаемого модуля ядра (драйвера устройства) управления удочкой был показан процесс написания модуля и процесс добавления к нему различных возможностей, таких как внешние параметры.
В следующей главе будут рассмотрены объекты kobject
и файловая система sysfs, которые являются основным интерфейсом к драйверам устройств и, следовательно, к модулям ядра.
Глава 17
Объекты kobject и файловая система sysfs
Унифицированная
• Уменьшается дублирование кода.
• Используется механизм для выполнения общих, часто встречающихся функций, таких как счетчики использования.
• Появляется возможность систематизации всех устройств в системе, возможность просмотра состояний устройств и определения, к какой шине то или другое устройство подключено.