среда, 4 января 2012 г.

Модули ядра FreeBSD

В этой статье будет рассмотрен обычный модуль, который выводит сообщение при его загрузке и выгрузке. Для этого ядро должно быть собрано с опцией SCHED_ULE. Также частота генерации прерываний должна быть снижена до 100, если ваша система запущена на виртуальной машине.
echo kern.hz=100 >> /boot/loader.conf

 Hello world
Для удобства сборки модуля есть специальный makefile /usr/src/share/mk/bsd.kmod.mk, который выполнит за вас всю работу по сборке модуля. Всё что нужно, это определить 2 вещи:
  • Имя модуля ядра через переменную “KMOD”;
  • Исходники модуля через переменную “SRCS”;
Дальше остается только вложить в ваш makefile bsd.kmod.mk

Makefile должен находиться в одной директории с нашим исходником.
Makefile:

# Важно чтобы вложение <bsd.kmod.mk> происходило после обьявления переменных KMOD и SRCS.

# Имя модуля
KMOD    =  hello_fsm

# Исходные файлы модуля
SRCS    =  hello_fsm.c

# makefile для модуля ядра
.include <bsd.kmod.mk>
Создание модуля
Теперь пришло время взглянуть на код модуля и механизмы вставки и извлечения модуля из ядра.
Модуль может быть добавлен в уже запущенное ядро. Когда модуль загружен, создается событие “load”. Когда модуль извлечен, создается событие “unload”. Сам модуль ответственен за поддержку этих событий.
Событие создается в форме символических констант, обьявленных в заголовочном файле /usr/include/sys/module.h (<sys/module.h>). Два основных события связаны с переменными MOD_LOAD and MOD_UNLOAD.
Модуль использует макрос DECLARE_MODULE для оповещения ядра. Ядро в свою очередь создает событие.
DECLARE_MODULE определен в <sys/module.h> и имеет четыре параметра:
  1. name. Имя.
  2. data. Структура типа moduledata_t (в примере - hello_conf). Тип moduledata_t определен в <sys/module.h>. Об этом ниже
  3. sub. Интерфейс подсистемы, который определяет тип модуля.
  4. order. Определяет порядок инициализации модулей в рамках определенной подсистемы.
Тип moduledata - это структура, содержащая переменную char, которая определяет имя, и обработчик события, определенный как структура modeventhand_t (определен в <sys/module.h>). Также moduledata содержит указатель типа void для дополнительных данных, который не будет использоваться.
Теперь у нас есть вся информация, пора её структурировать примером. Создайте файл hello_fsm.c в дирректории с Makefile'ом.
#include <sys/types.h>
#include <sys/param.h> 
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
Теперь нужно написать функцию, которую ядро вызовет и создаст событие MOD_LOAD или MOD_UNLOAD используя event параметр . Если все пойдёт как задуманно, то она вернет 0.
/* Функция, вызываемая при load/unload. */
static int event_handler(struct module *module, int event, void *arg) {
        int e = 0; /* 0 при нормальном завершении */
        switch (event) {
        case MOD_LOAD:
                uprintf("Hello World! \n");
                break;
        case MOD_UNLOAD:
                uprintf("Goodbye World!\n");
                break;
        default:
                e = EOPNOTSUPP; /* Ошибка */
                break;
        }
       
        return(e);
}
Теперь нужно определить второй параметр макроса DECLARE_MODULE, который имеет тип moduledata_t. Здесь вводятся имя и функция, которая будет вызвана при загрузке и выгрузке ядра.
static moduledata_t hello_conf = {
    "hello_fsm",    /* Имя модуля */
     event_handler,  /* Обработчик события */
     NULL            /* Дополнительные данные */
};
И наконец вызываем DECLARE_MODULE
DECLARE_MODULE(hello_fsm, hello_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
Теперь можно скомпилировать модуль
make
sudo kldload ./hello_fsm.ko

Должно появиться сообщение "Hello World!"

Источник: http://www.freesoftwaremagazine.com/

Комментариев нет:

Отправить комментарий