Kernel Programming

 

1. Compilare kernel

 

1.1 Kernel-ul linux este un program scris in C si asm. Sursele sale pot fi downloadate de pe http://kernel.org/, sau pot fi instalate cu apt-get install linux-source-2.6.x, unde x este un numar ce reprezinta versiunea dorita. Ultima versiune stabila de kernel este 2.6.29. Daca se alege varianta cu apt-get, sursele sunt copiate in folderul /usr/src.

 

1.2 La fel ca alte programe, kernel-ul poate fi compilat. Pentru compilare este nevoie de gcc, make si eventual alte pachete optionale.

 

1.3 Inainte de compilare, kernel-ul trebuie configurat. In timpul configurarii utilizatorul poate alege care componente sa fie incluse in viitorul kernel, si care sa fie lasate afara. Configurarea se poate face cu make config, make menuconfig, make xconfig, make gconfig, make oldconfig, make defconfig, make randconfig, etc. Cel mai utilizat mod de configurare pare sa fie make menuconfig (pentru care este nevoie de pachetul libncurses5-dev)

 

1.4 Dupa configurare, se compileaza kernelul impreuna cu modulele sale. Kernelul are o arhitectura ce permite inserarea sau eliminarea de module in timpul rularii, intr-un mod similar cu adaugarea sau eliminarea de plugin-uri.

make

make modules

 

1.5 Urmeaza instalarea kernelului si a modulelor. Prin instalare, executabilele compilate la pasul precedent sunt copiate din folderul cu sursele in locatiile in care se regasesc in mod normal (imaginea de kernel in /boot, iar modulele in /lib/modules

make modules_install

make install

 

1.6 In final, trebuie specificat ca la urmatorul boot, sa se poata alege rularea cu noul kernel. Linux permite existenta mai multor kernel-uri in acelasi timp, utilizatorul avand posibilitatea sa aleaga ce kernel sa incarce la boot-are.

 

How to: Compile Linux kernel 2.6

http://www.cyberciti.biz/tips/compiling-linux-kernel-26.html

 

 

2. Kernel programming

 

In cadrul laboratorului curent se prezinta un set de concepte si functii de baza necesare programarii kernel. Este important de retinut faptul ca programarea kernel difera extrem de mult fata de programarea în user-space. Kernel-ul este o entitate de sine statatoare, care nu poate folosi bibliotecile din user-space (nici chiar libc). Drept urmare, functiile uzuale utilizate în user-space (printf, malloc, free, open, read, write) nu mai pot fi folosite. În concluzie, programarea kernel se bazeaza pe un API nou si independent, ce nu are legatura cu API-ul din user-space.

 

Structura modulara a kernel-ului a fost realizata pentru a oferi programatorilor un mod simplu de a intra in kernel. Un modul de kernel (sau modul de kernel încarcabil) este un fisier obiect care contine cod ce poate extinde functionalitatea kernel-ului în timp real (este încarcat la nevoie); când un modul de kernel nu mai este necesar, acesta poate fi descarcat. Cea mai mare parte a driver-elor de dispozitiv (device drivers) sunt utilizate în forma de module de kernel.

 

Un modul este compilat prin intermediul unui fisier Makefile aflat in directorul /lib/modules/`uname -r`/build (uname -r este o comanda case indica versiunea curenta de kernel). Comanda de compilare este

 

make -C /lib/modules/`uname -r`/build M=`pwd`

 

In folderul curent trebuie sa existe un fisier Kbuild care sa indice numele programului de compilat. De exemplu, daca Kbuild contine linia obj-m = hello.o, se va obtine un modul cu numele hello.ko din sursa hello.c.

 

Fisierul modul (cel cu extensia ko) este inserat in kernel cu comanda insmod:

insmod hello.ko.

 

Alte 2 comenzi necesare sunt:

rmmod hello - descarca modulul cu numele hello (pentru rmmod nu se precizeaza extensia .ko)

lsmod - afiseaza toate modulele incarcate in momentul curent

 

Cel mai simplu modul de kernel este:

 

 

 

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/module.h>

 

MODULE_DESCRIPTION("My kernel module");

MODULE_AUTHOR("Me");

MODULE_LICENSE("GPL");

 

static int dummy_init(void)

{

printk(KERN_DEBUG "Hi\n");

return 0;

}

 

static void dummy_exit(void)

{

printk(KERN_DEBUG "Bye\n");

}

 

module_init(dummy_init);

module_exit(dummy_exit);

 

 

Odata cu inserarea modulului se executa functia specificata de module_init, iar la descarcarea modulului se executa functia specificata de module_exit.

 

Pentru a vedea mesajele afisate cu printk, se foloseste comanda dmesg.

 

In arhiva so5-examples.zip sunt mai multe exemple de module kernel, cu diverse functii. Fiecare folder contine un fisier Makefile, un fisier Kbuild si un fisier sursa. Pentru compilare se apeleaza make, iar pentru stergerea tuturor fisierelor generate se apeleaza make clean. Dupa compilare, functia de initializare din modul este rulata cu comanda insmod nume_modul.ko, iar cea de iesire este rulata cu comanda rmmod nume_modul.

 

Este necesara instalarea pachetului linux-headers-2.6.x-y (de ex. apt-get install linux-headers-2.6.24-22)

 

Pentru exercitiul 5, trebuie creat un fisier special (denumit de ex. /dev/abc) care reprezinta un device virtual de tip caracter. Acest "fisier" se foloseste pentru a se face legatura cu driver-ul nostru. Un device este identificat printr-o pereche de numere (major si minor) care in cazul nostru a fost aleasa ca 42 cu 0.

Astfel, comenzile necesare rularii exemplului 5 sunt:

sudo mknod /dev/abc c 42 0

sudo chmod 666 /dev/abc

---> compilare si incarcare driver <----

echo qwerty > /dev/abc

---> descarcare driver <----

dmesg