Еще мы должны помнить, что мы не можем позволять модулю выгружаться командой 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

Перейти на страницу:

Все книги серии Проект russian ldp

Похожие книги