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


Создание модулей для работы с разными версиями ядра



страница11/18
Дата21.11.2016
Размер1.25 Mb.
Просмотров4061
Скачиваний0
1   ...   7   8   9   10   11   12   13   14   ...   18

4.6. Создание модулей для работы с разными версиями ядра


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

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

Итак, мы уже поняли, что между разными версиями ядра могут существовать весьма существенные отличия. Если у вас появится необходимость в создании модуля, который мог бы работать с разными версиями ядра, то можете воспользоваться директивами условной компиляции, основываясь на сравнении макроопределений LINUX_VERSION_CODE и KERNEL_VERSION. Для версии a.b.c, макрос KERNEL_VERSION вернет код версии, вычисленный в соответствии с выражением: 2^{16}a+2^{8}b+c. Макрос LINUX_VERSION_CODE возвращает текущую версию ядра.

В предыдущих версиях данного руководства, довольно подробно описывалось, как писать обратно совместимый код, с использованием директив условной компиляции. Но, начиная с этой версии, мы решили порвать с устоявшейся традицией. Теперь, если вы желаете писать модули под определенные версии ядра, обращайтесь к соответствующей версии руководства (LKMPG). Мы решили выпускать этот документ под версиями (номер версии и номер подверсии), совпадающими с версиями обсуждаемого ядра. Таким образом, разработчики, работающие под ядро 2.4.x, должны обращаться к LKMPG версии 2.4.x, работающие под ядро 2.6.x -- к LKMPG версии 2.6.x и т.д.


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

5.1. Файловая система /proc: создание файлов, доступных для чтения


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

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

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

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

Пример 5-1. procfs.c

/*

* procfs.c - пример создания "файла" в /proc



*/
#include /* Необходимо для любого модуля */

#include /* Все-таки мы работаем с ядром! */

#include /* Необходимо для работы с файловой системой /proc */
struct proc_dir_entry *Our_Proc_File;
/* Обработчик чтения из файла в /proc.

*

* Аргументы



* =========

* 1. Буфер с данными. Как его заполнить -- вы решаете сами

* 2. Указатель на указатель на строку символов.

* Если вы не желаете использовать буфер

* размещенный ядром.

* 3. Текущая позиция в файле

* 4. Размер буфера.

* 5. Признак конца файла, "1" == EOF.

* 6. Указатель на данные (необходим в случае единственного

* обработчика на несколько файлов в /proc)

*

* Порядок использования и возвращаемое значение



* =============================================

* Нулевое значение == "буфер пуст", т.е. "Конец файла".

* Отрицательное значение == код ошибки.

*

* Дополнительные сведения



* =======================

* Основные принципы реализации этой функции

* я почерпнул не из документации, а из исходных текстов

* модулей, выполняющих подобные действия. Меня интересовало использование

* поля get_info в структуре proc_dir_entry (Если вам это интересно

* то для поиска я пользовался утилитами find и grep),

* Интересующий меня пример я нашел в

* directory>/fs/proc/array.c.

*

* Когда вам что-то непонятно, то лучше всего



* поискать примеры в исходных текстах ядра. В этом состоит

* огромное преимущество Linux перед другими ОС,

* так как нам доступны все исходные тексты, так что --

* пользуйтесь этим преимуществом!

*/

ssize_t


procfile_read(char *buffer,

char **buffer_location,

off_t offset, int buffer_length, int *eof, void *data)

{

printk(KERN_INFO "inside /proc/test : procfile_read\n");


int len = 0; /* Фактическое число байт */

static int count = 1;


/*

* Мы всегда должны выдавать имеющуюся информацию,

* если пользователь спрашивает -- мы должны ответить.

*

* Это очень важно, поскольку библиотечная функция read



* будет продолжать обращаться к системному вызову

* read до тех пор, пока ядро не ответит, что сведений больше нет

* или пока буфер не будет заполнен.

*/

if (offset > 0) {



printk(KERN_INFO "offset %d : /proc/test : procfile_read, \

wrote %d Bytes\n", (int)(offset), len);

*eof = 1;

return len;

}
/*

* Заполнить буфер и получить его размер

*/

len = sprintf(buffer,



"For the %d%s time, go away!\n", count,

(count % 100 > 10 && count % 100 < 14) ? "th" :

(count % 10 == 1) ? "st" :

(count % 10 == 2) ? "nd" :

(count % 10 == 3) ? "rd" : "th");

count++;
/*

* Вернуть размер буфера

*/

printk(KERN_INFO



"leaving /proc/test : procfile_read, wrote %d Bytes\n", len);

return len;

}
int init_module()

{

int rv = 0;



printk(KERN_INFO "Trying to create /proc/test:\n");
Our_Proc_File = create_proc_entry("test", 0644, NULL);
if (Our_Proc_File == NULL) {

rv = -ENOMEM;

remove_proc_entry("test", &proc_root);

printk(KERN_INFO "Error: Could not initialize /proc/test\n");

} else {

printk(KERN_INFO "Success!\n");

}
Our_Proc_File->read_proc = procfile_read;

Our_Proc_File->owner = THIS_MODULE;

Our_Proc_File->mode = S_IFREG | S_IRUGO;

Our_Proc_File->uid = 0;

Our_Proc_File->gid = 0;

Our_Proc_File->size = 37;


return rv;

}
void cleanup_module()

{

remove_proc_entry("test", &proc_root);



printk(KERN_INFO "/proc/test removed\n");

}

Пример 5-2. Makefile



obj-m += procfs.o


Каталог: files
files -> Основная часть 1 История создания школы
files -> Методические рекомендации по проведению Дня Знаний, посвященного Году кино в РФ
files -> Подросток и компьютерные игры
files -> Программа духовно-нравственного развития и воспитания обучающихся на уровне среднего общего образования
files -> Правила закаливания… Выпуск №1. Чтоб улыбка сияла. Мама первый стоматолог
files -> О существовании значения игры преследования
files -> Учебное пособие по нейрохирургии. Часть I. Краткая история нейрохирургии. Черепно-мозговая травма санкт-Петербург 2015


Поделитесь с Вашими друзьями:
1   ...   7   8   9   10   11   12   13   14   ...   18


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал