Модуль Hello World |
Предыдущая Содержание Следующая |
Многие книги по программированию начинаются с примера “hello world”, как способа создания простейшей программы. Эта книга посвящена созданию модулей ядра, а не программам; так что, нетерпеливый читатель, следующий код представляет собой завершённый модуль “hello world”:
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; }
static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); }
module_init(hello_init); module_exit(hello_exit);
В этом модуле определены две функции, одна вызывается, когда модуль загружается в ядро (hello_init), другая, когда модуль удаляется (hello_exit). Строчки с module_init и module_exit используют специальные макросы ядра, чтобы задать роль этих двух функций. Другой специальный макрос (MODULE_LICENSE) использован, чтобы сказать ядру, что этот модуль имеет свободную лицензию; без такой декларации при загрузке модуля ядро выводит предупреждение.
Функция printk определена в ядре Linux и доступна модулям; она ведёт себя аналогично стандартной библиотечной функции языка Си printf. Ядру необходима своя функция печати, поскольку оно работает само по себе, без помощи библиотек Си. Модуль может вызвать printk, потому что после того, как insmod загрузила его, модуль связан с ядром и может получить доступ к публичным символам ядра (функциям и переменным, это объясняется в следующем разделе). Определение KERN_ALERT - это приоритет сообщения. (* Приоритет - это просто строка, например, <1>, которая добавляется в начало строки форматирования printk. Обратите внимание на отсутствие запятой после KERN_ALERT; добавление запятой здесь - это частая и раздражающая опечатка (которая, к счастью, улавливается компилятором.))
Мы определили высокий приоритет в этом модуле, так как сообщения с приоритетом по умолчанию может быть не показано, это зависит от версии работающего ядра, версии демона klogd и ваших настроек. Вы можете проигнорировать сейчас этот вопрос; мы объясним это в Главе 4.
Вы можете протестировать модуль утилитами insmod и rmmod, как показано ниже. Обратите внимание, что только суперпользователь может загружать и выгружать модуль.
% make make[1]: Entering directory `/usr/src/linux-2.6.10' CC [M] /home/ldd3/src/misc-modules/hello.o Building modules, stage 2. MODPOST CC /home/ldd3/src/misc-modules/hello.mod.o LD [M] /home/ldd3/src/misc-modules/hello.ko make[1]: Leaving directory `/usr/src/linux-2.6.10' % su root# insmod ./hello.ko Hello, world root# rmmod hello Goodbye cruel world root#
Пожалуйста, обратите внимание ещё раз, чтобы указанная выше последовательность команд заработала, вы должны иметь правильно сконфигурированное и собранное дерево ядра там же, где Makefile будет искать его (/usr/src/linux-2.6.10 в показанном примере). Мы углубимся в детали сборки модулей в разделе "Компиляция и загрузка".
В зависимости от механизма, который используется в вашей системе для отображения сообщений, результат может быть другим. В частности, предыдущий снимок экрана был взят из текстовой консоли; если вы запускаете insmod и rmmod в эмуляторе терминала под управлением оконной системы, то вы не увидите ничего на экране. Сообщения отправятся в один из системных лог-файлов, таких как /var/log/messages (реальное имя файла разнится в дистрибутивах Linux). Механизм, используемый для доставки сообщений ядра описан в Главе 4.
Как вы можете видеть, написание модулей не так сложно, как можно было ожидать, по крайней мере, пока от модуля не требуется делать что-то полезное. Трудной частью является понимание работы устройства и как добиться максимальной производительности. Мы углубимся дальше в модуляризацию в этой главе и оставим вопросы специфики устройств следующим главам. |
Предыдущая Содержание Следующая |