Fuer uns wichtige Punkte im Source Baum:
Documantation/
Documentation/CodingStyle
include/linux -- API header files
include/asm -- Symlink auf Architektur-spezifische Header
kernel/ -- "Grundgeruest"
arch/ -- Architektur-abhaengiger Code
drivers/char/ -- Character-device-drivers
fs/*.c -- Filehandling
sonstiges:
init/ -- zum Booten des Kerns
ipc/ -- Inter Process Communication (Semaphoren, shared memory, ...)
drivers/ -- Treiber fuer alles moegliche (net, ide, input, pci, scsi, video,..)
fs/*/ -- Dateisysteme
mm/ -- Memory Management, alles rund um Pages
net/ -- Netzwerk Code
scripts/ -- Skrite die zum Bauen des Kerns benoetigt werden
security/ -- Security Module, diese haben Veto-Rechte auf einzelne Operationen
sound/ -- Sound-Treiber
usr/ -- userspace code fuer initramfs, derzeit nicht verwendet
Debugging schwierig, also aufpassen! Kein floating Point SMP & kernel preemption muessen bedacht werden
Wichtigste Optimierung: Code sollte schnell zu verstehen sein.
Es gibt einige Kernel Debugging Optionen, die einem helfen ein paar haeufige Fehler zu entdecken.
#include <linux/err.h> #include <linux/errno.h>
Check the return value! Most functions use negative return values to indicate an error. The actual value determines the kind of error (as defined in include/linux/errno.h). When an invalid parameter was encountered, -EINVAL is returned for example.
There are two different conventions for functions that return pointers:
return NULL in case of error (e.g. kmalloc)
return a special pointer indicating the actual error.
Be careful to check for the right condition! There are some macros to work with the second method:
return true if the given pointer is considered an error code
return the (negative) error code represented by the pointer
wrap the (negative) error code inside a pointer
If your function has to error-out, be careful to undo every step that already succeeded. The following structure is often used in the kernel to do that:
ret = register_foo(...); if (ret < 0) goto out;
ret = register_bar(...); if (ret < 0) goto out_foo;
ret = -ENOMEM; obj = kmalloc(...); if (obj == NULL) goto out_bar;
more_work(); err = 0; goto out;
out_bar: unregister_bar(...);
out_foo: unregister_foo(...);
out: return ret;
When any subfunction returns with an error, we undo everything in the reverse order and pass the return code to the calling function, which will do similiar things on its own. This is a little bit like C++ exceptions.