Basic Kernel Infrastructure

Printing Messages

#include <linux/kernel.h>

 printk(KERN_* "formatstring", ...)

aehnlich zu printf()

vor dem eigentlichen String kommt ein Prioritaetslevel:

 KERN_ERR, KERN_WARNING, ..., KERN_DEBUG
 pr_debug("formatstring", ...)

Ausgabe mit KERN_DEBUG nur bei #define DEBUG

 pr_info(...): Ausgabe mit KERN_INFO

Ausgaben sind praktisch immer moeglich, aber bei haeufig aufgerufenen Funktionen evtl. problematisch (z.B. Interrupt Handler)

Kritische Meldungen werden auf die Konsole ausgegeben. Die letzten Meldungen kann man sich auch per dmesg anzeigen lassen.

Allocating Memory

#include <linux/slab.h>

kmalloc & kfree -- kernel version von malloc & free

kmalloc hat im Gegensatz zu malloc noch ein Flags Argument: include/linux/gfp.h, meistens GFP_KERNEL oder GFP_ATOMIC. Nach Moeglichkeit GFP_KERNEL verwenden, aber geht nicht in kritischen Abschnitten oder Interrupt handlern, dort geht nur GFP_ATOMIC. GFP_ATOMIC findet allerdings haeufig keinen freien Speicher. Also: Speicherallokation moeglichst schon vorher mit GFP_KERNEL machen.

Auf jeden Fall: Rueckgabewert checken! (NULL bei Fehler)

Kontrolle ueber /proc/slabinfo

Accessing userspace memory

#include <asm/uaccess.h>

Userspace applications only have access to a limited

Sometimes the kernel has to access userspace memory. This memory may not be directly accessible even by the kernel, so there are some specialized functions to access that part of memory.

Access to userspace memory may fail if an invalid pointer was given. -EFAULT should be returned in this casse.

access_ok(type, addr, size)

Quick test to check for invalid addresses. type may be VERIFY_READ or VERIFY_WRITE.

get_user(var, addr)

read userspace memory at addr and store into variable var.

put_user(var, addr)

write variable var into userspace memory at addr

copy_from_user(to, from, n)

copy n bytes from userspace address from to kernel address to.

copy_to_user(to, from, n)

copy n bytes from kernel address from to userspace address to.

Be careful, the return values have different meanings for historical reasons: copy_to/from_user returns the number of bytes that could not be copied; the calling function is expected to return -EFAULT in this case. get/put_user already return -EFAULT or zero and access_ok returns 0 if the given address is invalid. You have to check the return value of get/put_user and copy_to/from_user even when access_ok says that the address is ok. The actual access to the memory could fail nevertheless.

Listing Objects

#include <linux/list.h>

 struct list_head {
 	struct list_head *next, *prev;
 };

Liste haeufig:

   l -->  a  <--> b <--> _c
    \____________________/|

in Linux:

   l  <-->  a
   ^        ^
   |        |
   \/      \/
   c  <-->  b

Eine Liste ist immer eine zirkulaere Struktur, l->next->prev == l, _immer_ Eine solche Liste hat immer mindestens ein Element, damit sind die ->next und ->prev Zeiger nie NULL. Ein Element wird als "Aufhaenger" verwendet, die anderen zum Verknuepfen der eigentlichen Listen-elemente. der list_head besitzt keinen eigenen data pointer, sondern wird meistens direkt in die aufzulistenden Strukturen eingebettet.

 INIT_LIST_HEAD(&list) creiert eine "leere" zyklische ein-element-Liste
 list_add(&entry, &list) fuegt ein Element hinzu
 list_del(&entry) loescht es wieder aus der Liste
 list_del_init(&entry) wie list_del und INIT_LIST_HEAD zusammen
 list_empty(&list) returns true if there is no other element in the list
 list_entry(&entry, container_type, container_member)
 list_for_each(iterator, &list)
 list_for_each_entry(ptr, &list, container_member)

...

Error codes

EINVAL

Generic error with some parameter.

EINTR

The system call was interrupted by a signal.

ERESTARTSYS

If a system call is interupted by a signal and returns -ERESTARTSYS then it will be restarted from the beginning if the SA_RESTART flag is set in the siginfo_t structure that was used to register the signal Handler. The system call will return the error code EINTR if SA_RESTART was not set.

EAGAIN

The requested action is not possible at this time. The systemcall would have to wait for something but the userspace process requested nonblocking operation (e.g. with O_NONBLOCK).

EFAULT

attempt to access invalid memory.

EIO

communication to a hardware device failed or the hardware device indicated an error.

EBUSY

some essential resource is not available.

ENOMEM

out of memory