přejít na obsah přejít na navigaci

Linux E X P R E S, Vývoj jádra II. – jednoduchý modul

Vývoj jádra II. – jednoduchý modul

V minulém dílu seriálu o vývoji součástí linuxového jádra jsme si shrnuli hlavní zásady, kterými by se měl každý vývojář řídit. Nyní přejdeme k samotnému vývoji. Na konci této kapitoly už by měl být každý schopen vytvořit, zkompilovat a načíst svůj vlastní modul. Lukáš Jelínek .


Co je potřeba ke kompilaci modulů

V první řadě potřebujeme samozřejmě kompilátor. Není třeba žádný speciální – náš důvěrně známý GCC plně vyhovuje. Předpokládám, že už ho každý má ve svém systému nainstalovaný (což je ostatně nutná podmínka pro kompilaci běžných programů); pokud tomu tak není, stačí doinstalovat z distribuce a nejlépe také aktualizovat na poslední stabilní verzi (ať už 3.x.x, nebo 4.x.x).

Další podmínkou je přítomnost zdrojových souborů jádra. Ty lze získat z oficiálního serveru (ftp.kernel.org), bývají také v distribucích. Některé distribuce obsahují kromě plných zdrojáků také „odlehčenou“ verzi – ta plně postačuje ke kompilaci modulů pro jádro, ke kterému přísluší, ale celé jádro z nich zkompilovat nelze. Pro experimenty stačí i tato odlehčená verze, v pozdějších fázích vývoje je lépe se uchýlit k plným zdrojovým textům. Programový kód musíme mít samozřejmě v čem napsat. Lze použít libovolný editor (vim, Emacs, Kate, jEdit apod.) nebo vývojové prostředí (Eclipse + CDT, KDevelop, Anjuta, Sun Studio atd.) – je to čistě záležitost vaší volby a chuti.

První kroky

Pro kompilaci nejjednoduššího modulu budeme potřebovat dva soubory. Samotný zdroják (prostě normální céčkovský soubor) a soubor Makefile. Postupně se na ně podíváme. Než k tomu ale dojde, bude dobré si připomenout, jak se s moduly jádra pracuje.

Uvažujme modul jako samostatný objekt, který máme někde na disku (typické místo pro nainstalované moduly je pod adresářem /lib/modules), odkud ho můžeme načíst do paměti. Moduly lze načítat prakticky kdykoliv, lze je i uvolňovat (odstraňovat) za běhu jádra. Zda a jak to probíhá, záleží na konfiguraci jádra. Obvykle můžeme moduly načítat v libovolnou chvíli a uvolňovat je také kdykoliv (kromě doby, kdy je někdo používá).

Pro manipulaci s moduly máme dvě skupiny programů: nízkoúrovňové (insmod, rmmod) a „inteligentní“ (modprobe). Ty doplňují ještě programy s informativní funkcí (lsmod, modinfo). Nízkoúrovňové programy pouze tupě vykonávají svou činnost – insmod zavede modul do paměti, rmmod ho uvolní. Program modprobe toho umí mnohem víc (a je také konfigurovatelný), v pravý čas se na něj podíváme podrobněji.

Stručné schéma práce programu insmod

Dobře napsaný modul (typicky funkcí printk()) informuje o všem, co je z hlediska správce systému důležité. Tyto informace si lze přečíst např. příkazem dmesg. Důkladně se na to podíváme v příštím dílu seriálu.

Funkce printk() je obdoba známé knihovní funkce printf(), ovšem místo na standardní výstup vypisuje do logovacího bufferu jádra. Odtud lze tyto informace získat programem dmesg a navíc se některé ze zpráv (podle úrovně závažnosti) dostanou i tam, kam směřuje logování jádra (bývají např. v souboru /var/log/messages).

Nejjednodušší modul

Vrhněme se tedy na napsání prvního jaderného modulu. Tento modul nebude dělat nic jiného, než že se bude umět zavést a uvolnit. Do souboru mymodule.c napíšeme text, který vidíte v rámci.

#include 
#include 
static int __init mymodule_init(void)
{
printk(KERN_INFO "mymodule: modul inicializovan\n");
return 0;
}
static void __exit mymodule_cleanup(void)
{
printk(KERN_INFO "mymodule: modul uvolnen\n");
}
module_init(mymodule_init);
module_exit(mymodule_cleanup);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Prvni zkusebni modul");
MODULE_AUTHOR("Lukas Jelinek ");

Kód modulu obsahuje dvě funkce – někomu možná připomenou konstruktor a destruktor dynamické sdílené knihovny. První z nich (inicializační) se volá při načítání modulu a její úspěšné dokončení je nutnou podmínkou k tomu, aby byl modul plně zaveden – to dá funkce najevo návratovou hodnotou 0. Pokud by vrátila zápornou hodnotu, znamená to neúspěch při zavádění – a program insmod vypíše zprávu příslušející danému kódu chyby (používají se záporné hodnoty chybových kódu, jak je známe z běžných knihovních funkcí – tedy např. EINVAL nebo EBUSY).

Druhá funkce zajišťuje úklid – volá se při uvolňování modulu a musí být napsána tak, aby v ní nikdy nic neselhalo. Pozor – pokud se modul zakompiluje přímo do jádra (nikoli samostatně), tato funkce se nikdy nezavolá.

Funkce je zvykem deklarovat jako static (i když to není nutné, je to z historických důvodů) a používají se u nich symboly __init a __exit. Tyto nepovinné symboly říkají, že se příslušná funkce volá pouze při inicializaci, resp. ukončení. Je to optimalizační záležitost (inicializační funkce se po načtení modulu odstraní z paměti; úklidová funkce se zase nezakompiluje do monolitického jádra, protože je tam zbytečná).

Pomocí maker module_init a module_exit určujeme, které funkce se používají pro inicializaci a úklid. Mohou být totiž pojmenovány libovolně. Vždy se doporučuje všechny funkce (tedy i ty, které se neexportují do jmenného prostoru jádra) pojmenovávat tak, aby název začínal (případně i zkráceným) názvem modulu – jak je ostatně v příkladu vidět. Předejdeme tím zmatkům a případným kolizím.

Na konci příkladu jsou tři speciální makra. Opět nejsou povinná, ale minimálně to licenční (MODULE_LICENSE) by se mělo vždy používat. Pro licenci GPL se použije uvedená forma zápisu, ale možností je poněkud více.

Modul bez zvolené licence (stejně jako ten s proprietární licencí) je jádrem považován za odpadlíka a nejenže bude uživateli hlásit, že je v jádře „cosi shnilého“, ale hlavně bude modulu odepřen přístup k některým symbolům. Pouze GPL-kompatibilní licence mají plnou podporu, proto by se mělo dávat jádru najevo, že modul takovou licenci má (bližší informace najdete v dokumentaci jádra).

Uvedení autora a popisu modulu je záležitostí ryze informativní – tyto údaje vypisuje např. utilita modinfo. Jsou užitečné, proto vřele doporučuji je vždy uvádět (u jména autora se obvykle uvádí i e-mailová adresa). Existují ještě další podobná makra, ale ta se používají méně.

Kompilujeme

Modul tedy máme napsaný, nastal proto čas ho zkompilovat. V adresáři s modulem si proto vytvoříme soubor Makefile. Protože využíváme systém KBUILD, bude obsah souboru vypadat trochu jinak, než jsme zvyklí z normálních programů. Lze postupovat různě, pro náš jednoduchý modul můžeme použít zápis, který vidíte v druhém rámci.

KDIR = /lib/modules/`uname -r`/build
obj-m := mymodule.o
all:
make -C $(KDIR) M=`pwd`
clean:
make -C $(KDIR) M=`pwd` clean

První řádek (definice proměnné KDIR) říká, kde se nachází zdrojový strom jádra. Uvedený způsob použije strom aktivního jádra (toho, které se právě používá), a to v rámci konvencí distribuce Fedora Core. Jiné distribuce mohou mít soubory uloženy jinde, proto se může příslušné cesta lišit.

Na druhém řádku určíme, jaký modul se bude kompilovat. Uvádí se v podobě objektového souboru. U jediného zdrojového (*.c) souboru si s tím vystačíme, při více souborech bude nutný trochu složitější zápis.

Pak tu máme ještě dvě pravidla – jsou velmi jednoduchá. Pro cíl all (a spuštění make bez parametrů) a pro cíl clean (odstranění souborů). Kompilovat se bude do aktuálního adresáře.

Máme-li soubor Makefile, můžeme začít kompilovat. Stačí v příslušném adresáři spustit make a vše potřebné by mělo proběhnout. Jsou-li zdroj i Makefile bezchybné, KBUILD pouze ohlásí, co kompiluje a již by mělo být hotovo. Po úspěšné kompilaci by v adresáři měl být (kromě meziproduktů) soubor s modulem připraveným k použití. Soubor má příponu .ko (kernel object), tedy v našem případě mymodule.ko.

Funguje to?

Zkusíme modul načíst příkazem insmod mymodule.ko. Pokud je vše v pořádku, měl by proces skončit bez vypsání jakékoli zprávy. Při chybě by sdělil, co je špatně. Pak můžeme příkazem dmesg zkontrolovat, zda modul vypsal, co měl (viz zdrojový kód). Modul lze uvolnit příkazem rmmod mymodule – i zde platí to, co jsem uvedl pro insmod.

Co dělat, když modul nefunguje, jak hledat chyby a hlavně jak jim předcházet, to bude náplní příštího dílu. Ladění a testování jádra je totiž (v porovnání s normálními programy) poněkud komplikovanější. Právě proto je potřeba využít všech prostředků k tomu, aby chyby vůbec nevznikaly.

Ještě bych rád upozornil, že obě tyto operace jsou (podobně jako další pokusy s načteným modulem) obecně nebezpečné. Pokud je v modulu chyba, může při jeho načítání nebo uvolňování počítač zatuhnout nebo se mohou poškodit data kdekoliv v paměti. Proto je důležité před zkoušením modulu ukončit všechny nepotřebné programy, zapsat data z paměti na disk (příkazem sync) a po skončení experimentů počítač restartovat.

Nahoru

Odkazy

Příspěvky

Vývoj jádra II. – jednoduchý modul
valesek 5. 12. 2007, 22:45:05
Odpovědět  Odkaz 
Ja jen chci reagovat na ten zdrojovej kod toho modulu, na radcich s #include chybi jmena souboru ktere tam vlastne chceme includovat, nylo by asi dobre je tam dodat. Dik. za tento serial.

valesek
Vývoj jádra II. – jednoduchý modul
nobody 16. 08. 2008, 17:07:08
Odpovědět  Odkaz 
Nevim cim to bude ale vypisuje mi to tyto chyby a pritom sem to presne zkopiroval nainstaloval sem kbuild a taky zmenil odsazeni v Makefile u radku 4 a 6 jinak to nejde zkompilovat.

http://leteckaposta.cz/264905355
Re:Vývoj jádra II. – jednoduchý modul
nobody 16. 08. 2008, 17:15:57
Odpovědět  Odkaz 
uz sem prisel na chybu je nutno vlozit tyto knihovny misto dvou prikazu pro preprocesor #include na zacatku
#include
#include
Vývoj jádra II. – jednoduchý modul
nobody 16. 08. 2008, 18:04:51
Odpovědět  Odkaz 
directivy se tam nezobrazili tak aspon sem dam odkaz kde je to videt
http://www.faqs.org/docs/kernel/x145.html#AEN152 jinak se omlouvam adminovi za toto "spamovani".
Vývoj jádra II. – jednoduchý modul
gaff 24. 09. 2013, 09:41:09
Odpovědět  Odkaz 
Kromě zmíněného #include je navíc třeba každé make v Makefile odsadit tabulátorem, jinak to při pokusu o kompilaci napíše "make: Nothing to be done for 'all'"
Lukáš Jelínek Re: Vývoj jádra II. – jednoduchý modul
Lukáš Jelínek 24. 09. 2013, 11:14:02
Odpovědět  Odkaz 
Tohle všechno jsou chyby, které vznikly před těmi více než 7 lety při konverzi z původního formátu (připraveného pro tištěný LinuxEXPRES) do verze pro web. I když už jsou ty informace těžce zastaralé, zkusím najít svůj původní autorský text a opravit to podle něj (něco lze rovnou, ale ty inkludy už z hlavy dohromady nedám).

Odpovědět

Nejsou podporovány žádné značky, komentáře jsou jen čistě textové. Více o diskuzích a pravidlech najdete v nápovědě.
Diskuzi můžete sledovat pomocí RSS kanálu rss



 
 

Top články z OpenOffice.cz

Lukáš Jelínek

Lukáš Jelínek

Dlouholetý člen autorského týmu LinuxEXPRESu a OpenOffice.cz. Vystudoval FEL ČVUT v oboru Výpočetní technika. Žije v Kutné Hoře, podniká v oblasti IT a zároveň pracuje v týmu projektu Turris. Ve volném čase rád fotografuje, natáčí a stříhá video, občas se věnuje powerkitingu a na prahu čtyřicítky začal hrát tenis.


  • Distribuce: Debian, Kubuntu, Linux Mint
  • Grafické prostředí: KDE

| proč linux | blog