Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Последовательности уведомлений



Механизм последовательностей уведомлений позволяет ядру регистрировать свой ин­терес к оповещению о появлении переменной асинхронного события. Этот обобщенный интерфейс распространяется на использование во всех подсистемах или компонентах ядра.

Последовательность уведомлений - это просто связанный список объектов notifier_block:

include/linux/notifier.h

14 struct notifier_block

15 {

16 int(*notifier_call)(struct notifier_block *self, unsigned long, void'*);

17 struct notifier_block *next;

18 int priority;

19 };

notif ier_block содержит указатель на функцию (notif ier_call) для вызова при наступлении события. Параметры этой функции включают указатель на notif ier_ block, содержащий информацию, значение, соответствующее событию, или флаг, и ука­затель на тип данных, определяемый подсистемой.

Кроме этого, структура notifier_block содержит указатель на следующий notif ier_block в последовательности и описание приоритета.

1 Как видно из отрывка кода, builtin_expect О обнуляется до версии GCC 2.96, потому что до этой

Версии GCC не обладал возможностью влиять на предсказание переходов.

Из этого отрывка это не следует; чтобы это увидеть, надо посмотреть на /usr/include/linux/compiler-gcc2.h.

Примеч. науч. ред.



Глава 2 • Исследовательский инструментарий


Функции not if ier_chain_register () и not if ier_chain_unregister ()

регистрируют и удаляют объект not if ier_block в указанной последовательности уведомлений.

Резюме

В этой главе описано достаточно информации, для того чтобы вы могли начать исследо­вание ядра Linux. Было описано два метода динамических хранилищ: связанные списки и деревья бинарного поиска. Полученные базовые знания об этих структурах помогут вам в дальнейшем при обсуждении других тем, например таких, как процессы и процесс под­качки. Затем мы рассмотрели основы языка ассемблера, что поможет вам в разборе кода или отладке на машинном уровне, и, акцентировав внимание на ассемблерных вставках, мы показали возможность совмещения С и ассемблера внутри одной функции. Мы за­кончили эту главу обсуждением различных команд и функций, необходимых для изуче­ния различных аспектов ядра.

Проект Hellomod

Этот раздел представляет базовые концепции, необходимые для понимания других Linux-концепций и структур, описанных далее в книге. Наши проекты концентрируются на создании загружаемых модулей, использующих новую, 2.6-архитектуру драйверов, и построении на базе этих модулей следующих проектов. Так как драйверы устройств могут быстро стать слишком сложными, нашей целью является только познакомить вас с базовыми конструкциями модулей Linux. Мы доработаем этот драйвер в следующих проектах. Данный модуль запускается как на РРС, так и на х86.

Шаг 1: написание каркаса модуля Linux

Первым модулем, который мы напишем, является символьный драйвер устройства «hello world». Сначала мы рассмотрим базовый код для модуля, а затем покажем, как его отком­пилировать с помощью новой системы Makefile 2.6 (это обсуждается в гл. 9), и нако­нец, присоединим и удалим наш модуль от ядра с использованием команд insmod и rramod соответственно1:

hellomod.с

// hello world driver for Linux 2.6

4 #include < linux/module.h>

5 #include < linux/kernel.h>

1 Убедитесь, что в вашей конфигурации включена поддержка выгрузки модулей.


Резюме



6 #include < linux/init.h>

7 #MODULE_LICENCE(" GPL" J1; //избавимся от ненужного сообщения

009 static int _ init lkp_init( void )

{

printk(,, < l> Hello/World! from the kernel space...\n" );

return 0; 013 }

015 static void _ exit lkp__cleanup ( void )

{

printk(" < l> Goodbye, World! leaving kernel space...\n" ); 018 }

20 module_init(lkp_init);

21 module_exit(lkp_cleanup);

Строка 4

Все модули используют заголовочный файл module. h, который должен быть под­ключен.

Строка 5

Файл kernel. h содержит основные функции ядра.

Строка 6

Заголовочный файл init.h содержит макросы_____ init и_____ exit. Эти макросы

позволяют освободить память ядра. Рекомендуем вам бегло ознакомиться с кодом и комментариями в этом файле.

Строка 7

Для предупреждения об отсутствии GNU открытой лицензии в ядре начиная с вер­сии 2.4 присутствует несколько специальных макросов. (За более подробной ин­формацией обращайтесь к файлу modules.h.)

Строки 9-12

Это функция инициализации нашего модуля. Эта функция должна, например, со­держать код создания и инициализации структур. В строке 11 мы можем послать со­общение из ядра с помощью printk (). Мы сможем увидеть это сообщение при загрузке нашего модуля.

1 В оригинальном тексте опечатка - должно быть '007 MODULE_LICENSE (" GPL" ); '. Примеч. науч. ред.



Глава 2 • Исследовательский инструментарий


Строки 15-18

Это функция выхода из нашего модуля и очистки памяти. Здесь мы прибираем все, связанное с нашим драйвером при его уничтожении.

Строка 20

Это точка инициализации драйвера. Ядро вызывает ее во время загрузки для встроенных модулей или во время подгрузки для загружаемых модулей.

Строка 21

Для загружаемых модулей ядро вызывает функцию cleanup_module (). Для встроенных модулей она не дает никакого эффекта.

Мы можем иметь в нашем драйвере только одну точку инициализации (module__init) и одну точку очистки (module_exit). Эти функции ядро ищет при загрузке и выгрузке нашего модуля.

Шаг 2: компиляция модуля

Если вы используете старые методы построения модуля ядра (например, те которые начинаются с #define MODULE), новый метод немного изменился. Для тех, кто впервые использует модуль 2.6, это будет довольно просто. Далее приведен базовый Makefile для нашего одного модуля.

Makefile

002 # Makefile for Linux Kernel Primer module skeleton (2.6.7)
006 obj-m += hellomod.o

Обратите внимание, что мы указываем системе сборки, что мы компилируем загружаемый модуль. Вызов для командной строки этого Makefile завернут в bash-скрипт, называемый doit следующего вида:

001 make -С /usr/src/linux-2.6.7 SUBDIRS=$PWD modules1

Строка 1

Опция -С указывает make изменить директорию исходников Linux (в нашем случае /usr/src/linux-2.6.7) перед чтением Makefile или другими действиями.

Перед выполнением. /doit вы увидите примерно следующий вывод:

Lkp#./doit

make: Entering directory •/usr/src/linux-2.6.7•

1 Удобно использовать следующую команду, которая не требует явным образом прописывать версию ядра: make -С /usr/src/linux-4uname -rN SUBDIRS=$PWD modules. Примеч. науч.ред.


Резюме



СС [М] /mysource/hellomod.o

Building modules, stage 2

MODPOST

CC /mysource/hellomod.o

LD [M] /mysource/hellomod.ko make: Leaving directory •/usr/src/linux-2.6.7• lkp# _

Для тех, кто компилировал или создавал модули Linux с помощью более ранних версий Linux, мы можем сказать, что теперь у нас есть шаг связывания LD и что нашим выходным модулем является hellomod. ко.

Шаг 3: запуск кода

Теперь мы готовы вставить новый модуль в ядро. Мы сделаем это с помощью команды insmod следующим образом:

lkp# insmod hellomod.ко

Для проверки того, что модуль был вставлен правильно, вы можете использовать ко­манду lsniod следующим образом:

lkp# lsmod

Module Size Used by

hellomod 2696 0

lkp#

Вывод нашего модуля генерируется с помощью printk (). Эта функция по умол­чанию выполняет печать в файл /var/log/messages. Для его быстрого просмотра на­печатайте следующее:

lkp# tail /var/log/mesasages

Это вывод 10 последних строк файла журнала. Вы увидите наше сообщение инициа­лизации:

Маг б 10: 35: 55 lkpl kernel: Hello, World! From the kernel space...

Для удаления нашего модуля (и просмотра нашего сообщения выхода) используйте команду rnmod с именем модуля, которое можно увидеть с помощью команды insmod. Для нашей программы эта команда будет выглядеть следующим образом:

Lkp# rnmod hellomod

И опять наш вывод в файле журнала будет выглядеть следующим образом:



Глава 2 • Исследовательский инструментарий


Маг б 12: 00: 05 lkpl kernel: Hello, World! From the kernel space...

В зависимости от настроек вашей Х-системы или используемой вами командной строки вывод printk пойдет на вашу консоль наравне с файлом журнала. В нашем сле­дующем проекте мы коснемся его снова при рассмотрении переменных системных задач.

Упражнения

1. Опишите, как в ядре Linux реализованы хеш-таблицы.

2. Структура, являющаяся членом дву связного списка, будет иметь структуру list_head. Перед вставкой структуры list_head в ядре структура будет иметь поля prev и next, указывающие на другие похожие структуры. Зачем создавать структуру только для хранения указателей prev и next?

3. Что такое ассемблерные вставки и почему вам может понадобиться их использо­вать?

4. Представьте, что вы пишете драйвер устройства, получающий доступ к регистрам последовательного порта. Объявите ли вы эти адреса как volatile? И если да, то почему.

5. Зная, что делает__ init, как вы думаете, какого рода функции могут использовать­ся с этим макросом?


Глава


з


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-25; Просмотров: 671; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.025 с.)
Главная | Случайная страница | Обратная связь