/*
* $Id: hello.c,v 1.10 hp.oser 17-08-2004
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; }
static void hello_exit(void) { printk(KERN_ALERT "Goodbye cruel world\n"); }
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
Dieses Programm kann unter Verwendung des nachfolgenden Makefile kompiliert werden:
#!/usr/bin/make
# Makefile for building hello driver as a module.
# $id$
# PREFIX may be set by the RPM build to set the effective root.
PREFIX=
ifeq ($(shell ls /lib/modules/$(shell uname -r)/build > /dev/null 2>&1 && echo build),)
ifeq ($(shell ls /usr/src/linux > /dev/null 2>&1 && echo linux),)
LINUX=
else
LINUX=/usr/src/linux
endif
else
LINUX=/lib/modules/$(shell uname -r)/build
endif
# check if 2.4 kernel or 2.5+ kernel
HELLO_KVER:=$(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/')
ifeq ($(HELLO_KVER), 2.6)
# Makefile for 2.5+ kernel
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
EXTRA_CFLAGS = -DDBG=0
else
default:
make -C $(LINUX) SUBDIRS=$(shell pwd) modules
endif
endif
clean:
-rm -f *.o *.ko
Der Kernelmodul kann mit der folgenden Anweisung ins Betriebssystem geladen werden:
# insmod hello.koDie Meldung
Hello, world wird normalerweise in die Datei
/var/log/messages geschrieben. Das Entfernen des Moduls aus dem System
erfolgt mit:
# rmmod hello #Die Meldung
Goodbye cruel world wird ebenfalls in die Datei
/var/log/messages geschrieben. Das Zusammenspiel zwischen dem Modul und
dem Kernel wird in der Abbildung 8 gezeigt.
Ein mit insmod geladener Modul bleibt speicherresident bis dieser Modul
wieder entfernt wird. Der Modul ist im Adressraum des Kernels, Programmfehler
in einem Modul können zum Absturz des Betriebssystems führen. Zu einem Kernel
Modul werden keine Libraries gelinkt, er darf aber (grundsätzlich) auf alle
Dienste des Kernels direkt zugreifen. Damit ein Modul/Treiber richtig
kompiliert müssen die Kernel Source Dateien installiert sein im Katalog
/usr/src/linux.
Module sind Kernel-Versionsabhängig und sollten für jede neue
Kernelversion neu übersetzt werden. Ein Modul kann auf Symbole des Kernels
oder anderer Module zugreifen. Zu diesem Zweck gibt es eine
Kernel-Symboltabelle die in der Datei /proc/ksyms enthalten ist.
Fehlerbehandlung im init_module()
Bei Auftreten eines Fehlers müssen alle vorgängigen register()
rückgängig gemacht werden sonst ist der Kernel in einem undefinierten
Zustand.
Usage Count
Für jeden Modul unterhält das Linux bis Version 2.4 einen usage
count. Mit folgenden Macros kann dieser Zähler angesprochen werden:
// to increment: MOD_INC_USE_COUNT // to decrement: MOD_DEC_USE_COUNT // to get TRUE if use count is zero: MOD_INI_USEAb Version 2.6 wird der usage count nicht mehr im eigenen Modul verändert weil dies zu Fehlern führen kann. Ein fremder Modul, der einen anderen Modul braucht erhöht den usage count mit:
int try_module_get(&module);Das Freigeben des Moduls erfolgt mit:
int module_put(&module);Automatische oder manuelle Konfiguration
// Deklaration von Variabeln im Treiber Modul int skull_ival=0; char *skull_sval;Anweisung zum Laden des Moduls://
# insmod skull skull_ival=99 skull_sval="mystring"Damit werden die Variabelnwerte dieser beiden Variabeln mit den neuen Werten überschrieben.
Kritische Abschnitte in Kernel-Mode Programmen
Auch im Kernel Mode ist es möglich, dass der Prozessor dem aktuellen Prozess
entzogen wird. Um sich vor allfälligen Problemen zu schützen sind folgende
Massnahmen bei shared data nötig:
unsigned long flags; local_save_flags(flags); local_irq_disable(); /* critical section */ local_irq_enable(); local_restore_flags(flags);besser, weil smp-safe:
typedef int spinlock_t; spinlock lock; spin_lock(&lock); /* critical section */ spin_unlock(&lock);
mmap für /dev/mem
und nur ein privilegierter Benutzer kann das durchführen.
ioperm oder iopl
aufgerufen wurde, dazu muss der Benutzer privilegiert sein.