Чтение онлайн

ЖАНРЫ

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

Померанц Ори

Шрифт:

Версии ядра Linux разделены между устойчивыми версиями (n.<Четное число>.m) и версии разработки (n.<Нечетное число>.m). Версии разработки включают все новые идеи, включая те, которые будут считаться ошибкой или повторно выполнены в следующей версии. В результате Вы не можете доверять интерфейсу в том плане, что он останется тем же самым в версиях разработки. В устойчивых версиях мы можем ожидать, что интерфейс останется тем же самым независимо от версии исправления ошибок (число m).

Эта версия MPG включает поддержку для версии 2.0.x и версии ядра Linux. Так как имеются различия между ними, требуется условная трансляция в зависимости от версии. Способ сделать

это сводится к тому, чтобы использовать макрокоманду LINUX_VERSION_CODE. В версии a.b.c ядра значение этой макрокоманды было бы 216a+28b+c. Чтобы получать значение для конкретной версии, мы можем использовать макрокоманду KERNEL_VERSION. Так как этот макрос не определен в 2.0.35, мы определяем его сами в случае необходимости.

Файловая система /proc

В Linux имеется дополнительный механизм для ядра и ядерных модулей, чтобы они могли послать информацию процессам: файловая система /proc. Первоначально разработанная для свободного доступа к информации относительно процессов, она теперь используется каждым кусочком ядра, который может что-либо сообщить, например, /proc/modules, который имеет список модулей и /proc/meminfo, который имеет статистику использования памяти.

Метод использования файловой системы /proc очень похож на работу с драйверами устройства: Вы создаете структуру со всей информацией, необходимой для /proc файла, включая указатели на любые функции драйвера (в нашем случае имеется только один, вызываемый когда кто-то пытается читать из /proc файла). Затем init_module регистрирует структуру и cleanup_module отменяет регистрацию.

Причина по которой мы используем proc_register_dynamic [2] в том, что мы не хотим определять inode номер, используемый для нашего файла заранее, но позволяем ядру определять его, чтобы предотвратить столкновения. В нормальных файловых системах размещенных на диске, а не только в памяти (как /proc) inode является указателем на то место, в котором на диске размещен индексный узел файла (кратко, inode). Inode содержит информацию относительно файла, например разрешения файла, вместе с указателем на то место, где могут быть найдены данные файла.

2

В версии 2.0, в версии 2.2 это выполняется для нас автоматически, если мы устанавливаем inode в ноль.

Поскольку никаких наших функций не вызывается когда файл открывается или закрывается, некуда поместить MOD_INC_USE_COUNT и MOD_DEC_USE_COUNT в этом модуле, и если файл открыт и затем модуль удален, не имеется никакого способа избежать проблем. В следующей главе мы рассмотрим более тяжелый в реализации, но более гибкий путь имеющий дело с файлами из /proc, который позволит нам защититься от этой проблемы.

procfs.c

/* procfs.c - create a "file" in /proc

* Copyright (C) 1998-1999 by Ori Pomerantz

*/

/* The necessary header files */

/* Standard in kernel modules */

#include <linux/kernel.h> /* We're doing kernel work */

#include <linux/module.h> /* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */

#if CONFIG_MODVERSIONS==1

#define MODVERSIONS

#include <linux/modversions.h>

#endif

/* Necessary because we use the proc fs */

#include <linux/proc_fs.h>

/* 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

/* Put data into the proc fs file.

 Arguments

 =========

 1. The buffer where the data is to be inserted, if you decide to use it.

 2. A pointer to a pointer to characters. This is useful if you don't want to use the buffer allocated by the kernel.

 3. The current position in the file.

 4. The size of the buffer in the first argument.

 5. Zero (for future use?).

Usage and Return Value

 ======================

 If you use your own buffer, like I do, put its location in the second argument and return the number of bytes used in the buffer.

 A return value of zero means you have no further information at this time (end of file). A negative return value is an error condition.

 For More Information

 ====================

 The way I discovered what to do with this function wasn't by reading documentation, but by reading the code which used it. I just looked to see what uses the get_info field of proc_dir_entry struct (I used a combination of find and grep, if you're interested), and I saw that it is used in <kernel source directory>/fs/proc/array.c.

 If something is unknown about the kernel, this is usually the way to go. In Linux we have the great advantage of having the kernel source code for free - use it.

*/

int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int zero) {

 int len; /* The number of bytes actually used */

 /* This is static so it will still be in memory
 when we leave this function */

 static char my_buffer[80];

 static int count = 1;

 /* We give all of our information in one go, so if the

Поделиться с друзьями: