Если в ядре происходит ошибка, у Вас больше шансов получить из ядра отладочные сообщения, если Вы работаете в текстовой консоли, чем если Вы работаете в X. Вне X вывод printk идет непосредственно с ядра на консоль. В X printk идет на процесс режима пользователя (xterm -C). Когда этот процесс получает время CPU, предполагается послать дааные X процессу. Затем, когда X сервер получает время, сообщение отобразится, но нестабильное ядро обычно означает, что система собирается разрушиться или перезагружаться, так что Вы не успеете получить сообщения об ошибках, которые могли бы объяснить Вам, что именно пошло неправильно. Так что, никаких иксов!
Модули ядра из нескольких файлов
Иногда имеет смысл разделить модуль на несколько файлов. В этом случае Вы должны делать следующее:
1. Во всех исходных файлах добавьте строку #define __NO_VERSION__. Это важно, потому что module.h обычно включает определение kernel_version, глобальная переменная версии ядра для которой компилируется модуль. Если Вы нуждаетесь в version.h, Вы должны включить его непосредственно, потому что module.h не будет делать этого после указания __NO_VERSION__.
2. Скомпилируйте все исходные файлы как обычно.
3. Объедините все объектные файлы в один. Под x86 это делается командой:
ld -m elf_i386 -r -o <���имя_модуля>.o <1-ый исходный файл>.o <2-ой исходный файл>.o.
Пример такого модуля:
start.c
/* start.c
* Copyright (C) 1999 by Ori Pomerantz
*
* "Hello, world" - the kernel module version.
* This file includes just the start routine
*/
/* 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
/* Initialize the module */
int init_module() {
printk("Hello, world - this is the kernel speaking\n");
/* If we return a non zero value, it means that
* init_module failed and the kernel module
* can't be loaded */
return 0;
}
stop.c
/* stop.c
* Copyright (C) 1999 by Ori Pomerantz
*
* "Hello, world" - the kernel module version. This
* file includes just the stop routine.
*/
/* The necessary header files */
/* Standard in kernel modules */
#include /* We're doing kernel work */
#define __NO_VERSION__ /* This isn't "the" file of the kernel module */
#include /* Specifically, a module */
#include /* Not included by module.h because of the __NO_VERSION__ */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include
#endif
/* Cleanup - undid whatever init_module did */
void cleanup_module(){
printk("Short is the life of a kernel module\n");
}
Makefile
# Makefile for a multifile kernel module
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX
hello.o: start.o stop.o
ld -m elf_i386 -r -o hello.o start.o stop.o
start.o: start.c /usr/include/linux/version.h
$(CC) $(MODCFLAGS) -c start.c
stop.o: stop.c /usr/include/linux/version.h
$(CC) $(MODCFLAGS) -c stop.c
Файлы символьных устройств
Имеются два главных пути для общения модуля разговаривать с процессами. Первый идет через файлы устройства (подобно файлам в каталоге /dev), другой должен использовать файловую систему proc. Поскольку одной из главных причин написания модуля ядра, является поддержка некоего аппаратного устройства, мы начнем с файлов устройства.
Первоначальная цель файлов устройства состоит в том, чтобы позволить процессам связываться с драйверами устройства в ядре, и через них с физическими устройствами (модемы, терминалы, и т.д.).
Каждый драйвер устройства, который является ответственным за некоторый тип аппаратных средств, имеет собственный главный номер. Список драйверов и их главных номеров доступен в /proc/devices. Каждое физическое устройство, управляемое драйвером устройства имеет малый номер. Каталог /dev включает специальный файл, названный файлом устройства, для каждого из тех устройств, которые реально установлены в системе.
Например, если Вы даете команду ls -l /dev/hd[ab]*, вы увидите все IDE разделы жесткого диска, которые могли бы быть связаны с машиной. Обратите внимание, что все из них используют тот же самый главный номер, 3, но малые номера у каждого свои! Оговорка: Считается, что вы используете архитектуру PC. Я не знаю ничего относительно файлов устройств Linux на других архитектурах .
Когда система была установлена, все файлы устройств были созданы командой mknod. Не имеется никакой технической причины, по которой они должны быть в каталоге /dev, это только полезное соглашение. При создании файла устройства для целей тестирования, как с упражнением здесь, вероятно имело бы смысл поместить его в каталог, где Вы компилируете модуль.
Читать дальше