Энциклопедия разработчика модулей ядра Linux - [4]

Шрифт
Интервал

Драйвер устройства выполняет четыре действия (функции), которые вызываются, когда кто-то пробует делать что-либо с файлом устройства, который имеет наш главный номер. Ядро знает, что вызвать их надо через структуру file_operations, Fops, который был дан, когда устройство было зарегистрировано, включает указатели на те четыре функции, которые данное устройство выполняет.

Еще мы должны помнить, что мы не можем позволять модулю выгружаться командой rmmod всякий раз, когда root захочет его выгрузить. Причина в том что, если файл устройства открыт процессом, и мы удаляем модуль, то использование файла вызвало бы обращение к точке памяти где располагалась соответствующая функция. Если мы удачливы, никакой другой код не был загружен туда, и мы получим уродливое сообщение об ошибках. Если мы неудачливы (обычно так и бывает), другой модуль был загружен в то же самое место, что означает переход в середину другой функции внутри ядра. Результаты этого невозможно предсказывать, но они не могут быть положительны.

Обычно, когда Вы не хотите выполнять что-либо, Вы возвращаете код ошибки (отрицательное число) из функции, которая делает данное действие. С cleanup_module такой фокус не пройдет: если cleanup_module вызван, модуль завершился. Однако, имеется счетчик использований, который считает, сколько других модулей используют этот модуль, названный номером ссылки (последний номер строки в /proc/modules). Если это число не нулевое, rmmod будет терпеть неудачу. Счетчик модульных ссылок доступен в переменной mod_use_count_. Так как имеются макрокоманды, определенные для обработки этой переменной (MOD_INC_USE_COUNT и MOD_DEC_USE_COUNT), мы предпочитаем использовать их, а не mod_use_count_ непосредственно, так что мы будем в безопасности, если реализация изменится в будущем.

chardev.c

>/* chardev.c

>* Copyright (C) 1998-1999 by Ori Pomerantz

>*

>* Create a character device (read only)

>*/


>/* The necessary header files */

>/* Standard in kernel modules */

>#include /* We're doing kernel work */

>#include /* Specifically, a module */


>/* Deal with CONFIG_MODVERSIONS */

>#if CONFIG_MODVERSIONS==1

>#define MODVERSIONS

>#include

>#endif


>/* For character devices */

>#include /* The character device definitions are here */

>#include /* A wrapper which does next to nothing at present, but may help for compatibility with future versions of Linux */


>/* In 2.2.3 /usr/include/linux/version.h includes a macro for this, but 2.0.35 doesn't - so I add it here if necessary. */

>#ifndef KERNEL_VERSION

>#define KERNEL_VERSION(a,b,c)

>((a)*65536+(b)*256+(c))

>#endif


>/* Conditional compilation. LINUX_VERSION_CODE is the code (as per KERNEL_VERSION) of this version. */

>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)

>#include /* for put_user */

>#endif


>#define SUCCESS 0

>/* Device Declarations **************************** */

>/* The name for our device, as it will appear in /proc/devices */

>#define DEVICE_NAME "char_dev"


>/* The maximum length of the message from the device */

>#define BUF_LEN 80


>/* Is the device open right now? Used to prevent concurent access into the same device */

>static int Device_Open = 0;


>/* The message the device will give when asked */

>static char Message[BUF_LEN];


>/* How far did the process reading the message get? Useful if the message is larger than the size of the buffer we get to fill in device_read. */

>static char *Message_Ptr;


>/* This function is called whenever a process attempts to open the device file */

>static int device_open(struct inode *inode, struct file *file) {

> static int counter = 0;

>#ifdef DEBUG

> printk("device_open(%p,%p)\n", inode, file);

>#endif

>/* This is how you get the minor device number in case you have more than one physical device using the driver. */

> printk("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF);

> /* We don't want to talk to two processes at the same time */

> if (Device_Open) return -EBUSY;

> /* If this was a process, we would have had to be

> * more careful here.

> *

> * In the case of processes, the danger would be

> * that one process might have check Device_Open

> * and then be replaced by the schedualer by another

> * process which runs this function. Then, when the

> * first process was back on the CPU, it would assume

> * the device is still not open.

> *

> * However, Linux guarantees that a process won't be

> * replaced while it is running in kernel context.

> *

> * In the case of SMP, one CPU might increment

> * Device_Open while another CPU is here, right after

> * the check. However, in version 2.0 of the

> * kernel this is not a problem because there's a lock

> * to guarantee only one CPU will be kernel module at

> * the same time. This is bad in terms of

> * performance, so version 2.2 changed it.

> * Unfortunately, I don't have access to an SMP box

> * to check how it works with SMP. */

> Device_Open++;

> /* Initialize the message. */

> sprintf(Message, "If I told you once, I told you %d times - %s", counter++, "Hello, world\n");

> /* The only reason we're allowed to do this sprintf


Рекомендуем почитать
Графика DirectX в Delphi

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


Вторая жизнь старых компьютеров

Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.


DirectX 8. Начинаем работу с DirectX Graphics

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.