1 [[!meta title="Embedded Linux"]]
8 Open source projekty se často nepoužívají osamoceně, ale v kombinaci s
9 jinými OSS projekty, čímž vznikají tak tzv. OSS stacky. Asi
10 nejznámějším stackem je LAMP – Linux, Apache, MySQL, PHP. Na dnešním
11 cvičení se seznámíme s dalším, velmi často používaným, stackem
12 [Linux][kenrel] + [BusyBox][bb] (+[Dropbear][dropbear] SSH server).
14 [BusyBox][bb] je sada UNIXových uživatelských nástrojů (shell, editor,
15 utility jako ls, mkdir, …) zkompilovaná do jedné binárky. V kombinaci
16 s jádrem Linuxu tak dostáváme kompletní operační systém s poměrně
17 malými nároky na paměť. Díky tomu se tato kombinace často používá ve
18 vestavěných (embedded) aplikacích jako například
19 [WiFi routery či ADSL modemy][owrt].
21 V tomto cvičení si zkusíte vytvořit kompletní open source operační
22 systém z Linuxového jádra a uživatelského prostředí tvořeného právě
23 BusyBoxem. Dále si vyzkoušíte naprogramovat jednoduchý modul do jádra.
25 [kenrel]: http://kernel.org/
26 [bb]:http://busybox.net/
27 [owrt]:http://www.openwrt.org/
28 [dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
33 1. Stáhneme [zdrojové kódy][bbgit] projektu [BusyBox][bb]:
35 git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
38 [bbgit]:http://git.busybox.net/busybox/
40 2. Zkonfigurujeme jak chceme BusyBox přeložit.
44 Vystačíme s výchozí konfigurací, takže zvolit `Exit` a odpovědět
45 `Yes`, že chceme konfiguraci uložit.
47 3. Kompilaci provedeme tradičně příkazem
55 nainstalujeme busybox do adresáře `./_install`. Všimněte si, že se
56 tam nachází pouze jedna binárka `bin/busybox` a všechno ostatní
57 jsou pouze symbolické odkazy na tuto binárku.
59 Protože neprovádíme tzv. *křížový překlad*, který je běžný pro v
60 případě vestavěných zařízení, můžeme výsledek hned otestovat
61 například spuštěním shellu: `./_install/bin/sh` (ukončíme ho např.
64 V případě skutečného vestavěného systému bychom museli pokračovat
65 dál a bysybox otestovat až po nabootování na cílovém hardwaru.
67 5. Pokud máte na vašem počítači práva superuživatele root, můžete
68 otestovat BusyBox v chroot prostředí, t.j. se stejným jádrem jako
69 právě běží na vašem počítači, ale se souborovým systémem tvořeným
72 # chroot _install /bin/sh
74 Fungovat to ale nebude, protože ke spuštění BusyBoxu jsou potřeba
75 knihovny, které v nejsou v adresáři `_install` dostupné.
77 6. Chybějící knihovny zjistíte příkazem
79 ldd _install/bin/busybox
81 Tyto knihovny musíte nakopírovat do adresáře `_install`
84 cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
86 Nyní už můžete spustit BusyBox v chroot prostředí.
88 5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
89 uživatelského prostředí je uložit ho ve formátu pro Linuxový
90 startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
92 Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
93 RAM-disk obsahovat i někoik položek v adresáři `/dev` pro přístup k
94 virtuálním terminálům.
96 1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
98 mkdir _install/{dev,etc,proc,sys}
99 sudo cp -a /dev/tty? _install/dev
100 ln -s bin/busybox _install/init
101 (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
103 2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástoje
104 [gen_init_cpio][gic].
109 nod /dev/tty0 644 0 0 c 4 0
110 nod /dev/tty1 644 0 0 c 4 1
111 nod /dev/tty2 644 0 0 c 4 2
112 nod /dev/tty3 644 0 0 c 4 3
113 nod /dev/tty4 644 0 0 c 4 4
114 slink /init bin/busybox 700 0 0
119 find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
120 find _install -type f -printf "file /%P %p %m 0 0\n"
121 find _install -type l -printf "slink /%P %l %m 0 0\n"
124 gen_init_cpio filelist > ramdisk
126 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD
128 5. **Jádro Linuxu**. Příprava jádra je téměř stejná jako u BusyBoxu:
129 stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
130 rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
131 trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
134 Pokud byste si chtěli přeložit vlastní jádro, v následujícím
135 příkazu byste za parametrem *-kernel* uvedli cestu k vámi
136 zkompilovanému jádru.
138 6. Bootování jádra s naším filesystémem (v emulátoru):
140 qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
142 7. Pokud vše proběhlo správně, zobrazila se hláška
144 Please press Enter to activate this console.
146 Po stisku Enteru se spustí shell a můžete začít pracovat ve
147 vašem právě vytvořeném systému.
152 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
153 zjednodušit další práci.
155 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
156 jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
157 emulátoru, ne na vaší pracovní stanici.
159 mount -t proc none /proc
161 2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
162 obsahovat příkazy, které budou spuštěny při bootu systému.
164 mkdir -p _install/etc/init.d
165 cat <<EOF > _install/etc/init.d/rcS
167 mount -t proc none /proc
170 chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
172 Nyní musíte znovu vytvořit RAM-disk a nabootovat.
177 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
178 Linuxvého jádra. Pokud bychom chtěli nalézt analogickou věc v
179 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
180 modul může obsahovat kód ovladače zařízení, podporu určitého
181 souborového systému, může přidávat do jádra nové funkce (např.
182 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
185 Zdrojový kód jednoduchého jaderného modulu vypadá následovně:
187 #include <linux/init.h>
188 #include <linux/module.h>
189 MODULE_LICENSE("Dual BSD/GPL");
191 static int hello_init(void)
193 printk(KERN_ALERT "Hello, world\n");
197 static void hello_exit(void)
199 printk(KERN_ALERT "Goodbye, cruel world\n");
202 module_init(hello_init);
203 module_exit(hello_exit);
204 *Příklad převzat z [LDD3][LDD3].*
206 Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
207 bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
208 soubor se jmenuje khello.c):
212 Nyní stačí zavolat `make` se správnými parametry:
214 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
216 Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
217 zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
218 můžete zjistít pomocí `readlink -f /lib/modules/$(uname -r)/build`),
219 pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
220 adresáři a slovo `modules` na konci znamená, že chcete, aby se
221 zkompilovaly pouze moduly.
223 Pokud vše dopadlo dobře, objevil se vám soubor `khello.ko`, což je
224 modul, který můžete zavést do jádra příkazem
233 Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
234 vaše jméno (objeví se ve výstupu `dmesg`). Jinak nemusí dělat nic.
235 Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
238 Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
239 objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
240 který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
241 v [tomto článku][henson_drivers] (strany 2 a 3).
246 * Pro vyvolání určitého příkazu z historie můžete použít klávesu
247 `Ctrl-R` následovanou textem hledaného příkazu. Např:
254 * [ramfs, rootfs and initramfs](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/filesystems/ramfs-rootfs-initramfs.txt;hb=HEAD)
255 * [Early userspace support](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/early-userspace/README;hb=HEAD)
256 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)
257 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)
258 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
259 * [Linux Device Drivers, Third Edition][LDD3]
260 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
261 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
263 [LDD3]:http://lwn.net/Kernel/LDD3/
264 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html