1 [[!meta title="Embedded Linux"]]
8 Cílem tohoto cvičení je prakticky si procvičit informace probírané na
9 2. přednášce a motivovat vás ke 4. přednášce "*Linuxové jádro – vznik,
10 vývoj, skladba a ovladače; GNU libc a uživatelský prostor*". Pokud vám
11 nejsou jasné některé souvislosti, doporučujeme zkusit si informace
12 vygooglovat a připravit si otázky na 4. přednášku.
14 Open source software (OSS) projekty se často nepoužívají osamoceně,
15 ale v kombinaci s jinými OSS projekty, čímž vznikají tak tzv. OSS
16 stacky. Asi nejznámějším stackem je LAMP – Linux, Apache, MySQL, PHP.
17 Na dnešním cvičení se seznámíme s dalším, velmi často používaným,
18 stackem [Linux][kenrel] + [BusyBox][bb] (+[Dropbear][dropbear] SSH
21 [BusyBox][bb] je sada UNIXových uživatelských nástrojů (shell, editor,
22 utility jako ls, mkdir, …) zkompilovaná do jedné binárky. V kombinaci
23 s jádrem Linuxu tak dostáváme kompletní operační systém s poměrně
24 malými nároky na paměť. Díky tomu se tato kombinace často používá ve
25 vestavěných (embedded) aplikacích jako například
26 [WiFi routery či ADSL modemy][owrt].
28 V tomto cvičení si zkusíte vytvořit kompletní open source operační
29 systém z Linuxového jádra a uživatelského prostředí tvořeného právě
30 BusyBoxem. Dále si vyzkoušíte naprogramovat jednoduchý modul do jádra.
32 [kenrel]: http://kernel.org/
33 [bb]:http://busybox.net/
34 [owrt]:http://www.openwrt.org/
35 [dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
40 1. Stáhneme [zdrojové kódy][bbgit] projektu [BusyBox][bb]:
42 git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
45 Protože se jedná o aktuální vývojový snapshot, je možné, že se
46 při překladu, instalaci nebo používání vyskytne chyba. Naší výhodou
47 však je, že máme k dispozici kompletní historii projektu
51 a můžeme si vybrat verzi, kde se chyba nevyskytuje. Například
53 git checkout -f 1_18_3
55 [bbgit]:http://git.busybox.net/busybox/
57 2. Zkonfigurujeme jak chceme BusyBox přeložit.
61 Vystačíme s výchozí konfigurací, takže zvolte `Exit` a odpovězte
62 `Yes`, že chcete konfiguraci uložit.
64 3. Kompilaci provedeme tradičně příkazem
72 nainstalujeme busybox do adresáře `./_install`. Všimněte si (`ls
73 -lR _install`), že se tam nachází pouze jedna binárka `bin/busybox`
74 a všechno ostatní jsou pouze symbolické odkazy na tuto binárku.
76 Protože neprovádíme tzv. *křížový překlad* (cross compilation),
77 který je běžný v případě vestavěných zařízení, můžeme výsledek
78 hned otestovat například spuštěním shellu: `./_install/bin/sh`
79 (ukončíme ho např. příkazem `exit`).
81 V případě skutečného vestavěného systému bychom museli pokračovat
82 dál a busybox otestovat až po nabootování na cílovém hardwaru.
84 5. Pokud máte na svém počítači práva uživatele `root`, můžete
85 otestovat BusyBox v [chroot prostředí][chroot], t.j. se stejným jádrem jako
86 právě běží na vašem počítači, ale se souborovým systémem tvořeným
89 # chroot _install /bin/sh
91 Fungovat to ale nebude, protože ke spuštění BusyBoxu jsou potřeba
92 knihovny, které v nejsou v adresáři `_install` dostupné.
94 [chroot]:http://en.wikipedia.org/wiki/Chroot
96 6. Chybějící knihovny zjistíte příkazem
98 ldd _install/bin/busybox
100 Tyto knihovny musíte nakopírovat do adresáře `_install`. Na
101 32-bitovém systému to může vypadat například takto:
104 cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
106 Na 64-bitovém systému jádro hledá pro dynamicky linkované programy
107 "interpreter" `/lib64/ld-linux-x86-64.so.2` v adresáři `/lib64`.
108 Vytvoříme ho jako symbolický odkaz na adresář `/lib`
110 ( cd _install && ln -s lib lib64 )
112 Nyní už můžete spustit BusyBox v chroot prostředí.
114 5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
115 uživatelského prostředí je uložit ho ve formátu pro Linuxový
116 startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
118 Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
119 RAM-disk obsahovat i několik položek v adresáři `/dev` pro přístup k
120 virtuálním terminálům.
122 1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
124 mkdir _install/{dev,etc,proc,sys}
125 sudo cp -a /dev/tty? _install/dev
126 ln -s bin/busybox _install/init
127 (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
129 2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
130 [gen_init_cpio][gic].
135 nod /dev/tty0 644 0 0 c 4 0
136 nod /dev/tty1 644 0 0 c 4 1
137 nod /dev/tty2 644 0 0 c 4 2
138 nod /dev/tty3 644 0 0 c 4 3
139 nod /dev/tty4 644 0 0 c 4 4
140 slink /init bin/busybox 700 0 0
145 find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
146 find _install -type f -printf "file /%P %p %m 0 0\n"
147 find _install -type l -printf "slink /%P %l %m 0 0\n"
150 gen_init_cpio filelist | gzip > ramdisk
152 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD
154 5. **Jádro Linuxu**. Příprava jádra je téměř stejná jako u BusyBoxu:
155 stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
156 rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
157 trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
160 Pokud byste si chtěli přeložit vlastní jádro, v následujícím
161 příkazu byste za parametrem *-kernel* uvedli cestu k vámi
162 zkompilovanému jádru.
164 6. Bootování jádra s naším filesystémem (v emulátoru):
166 Na 32-bitovém systému spustíme emulátor následovně:
168 qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
170 Na 64-bitovém systému může být potřeba použít příslušnou variantu QEMU:
172 qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
174 Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
175 použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
177 kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
179 [kvm]:http://www.linux-kvm.org/
181 7. Pokud vše proběhlo správně, zobrazila se hláška
183 Please press Enter to activate this console.
185 Po stisku Enteru se spustí shell a můžete začít pracovat ve
186 vašem právě vytvořeném systému.
191 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
192 zjednodušit další práci.
194 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
195 jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
196 emulátoru, ne na vaší pracovní stanici.
198 mount -t proc none /proc
200 2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
201 obsahovat příkazy, které budou spuštěny při bootu systému.
203 mkdir -p _install/etc/init.d
204 cat <<EOF > _install/etc/init.d/rcS
206 mount -t proc none /proc
209 chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
211 Nyní musíte znovu vytvořit RAM-disk a nabootovat.
213 3. Zachytávání zpráv jádra spuštěného v emulátoru QEMU do souboru
214 je možné jejich přesměrování na virtuální sériový port.
215 Požadavek na jeho vytvoření se předá QEMU zadáním parametru
217 qemu -serial file:/tmp/virtual_guest.log ...
219 a jádro spustíme s parametrem `console=ttyS0`
221 qemu -serial file:/tmp/virtual_guest.log -append console=ttyS0 ...
223 4. Připojení virtuálního stroje na vější síť s využitím NAT na uživatelské úrovni.
225 qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
227 5. Pokud QEMU nebo KVM podporuje vytvoření virtio sítě Plan9 a virtuálního
228 souborového systému, tak je možné propagovat do vnitřního systému
229 obsah adresáře hostitelského sytému
231 qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
233 Adresářovou strukturu lze z vnitřního systému připojit následujícími
240 modprobe 9pnet_virtio
242 mkdir -p /mnt/shareddir
243 mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
245 Další tipy a triky v oblasti virtualizace používané a odzkoušené zprávci
246 sítě na naší katedře nalezente na [Wiki Technické Podpory (support)][support-qemu].
247 [support-qemu]:http://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:Virtualiza%C4%8Dn%C3%AD_stroje
252 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
253 Linuxového jádra. Pokud bychom chtěli nalézt analogickou věc v
254 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
255 modul může obsahovat kód ovladače zařízení, podporu určitého
256 souborového systému, může přidávat do jádra nové funkce (např.
257 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
260 Zdrojový kód jednoduchého jaderného modulu vypadá následovně:
262 #include <linux/init.h>
263 #include <linux/module.h>
264 MODULE_LICENSE("Dual BSD/GPL");
266 static int hello_init(void)
268 printk(KERN_ALERT "Hello, world\n");
272 static void hello_exit(void)
274 printk(KERN_ALERT "Goodbye, cruel world\n");
277 module_init(hello_init);
278 module_exit(hello_exit);
279 *Příklad převzat z [LDD3][LDD3].*
281 Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
282 bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
283 soubor se jmenuje **khello.c**):
287 Nyní stačí zavolat `make` se správnými parametry:
289 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
291 Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
292 zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
293 můžete zjisti pomocí `readlink -f /lib/modules/$(uname -r)/build`),
294 pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
295 adresáři a slovo `modules` na konci znamená, že chcete, aby se
296 zkompilovaly pouze moduly.
298 Pokud vše dopadlo dobře, objevil se vám soubor `khello.ko`, což je
299 modul, který můžete zavést do jádra příkazem
308 Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
309 vaše jméno (objeví se ve výstupu příkazu `dmesg`). Jinak nemusí dělat nic.
310 Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
313 Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
314 objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
315 který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
316 v [tomto článku][henson_drivers] (strany 2 a 3).
321 * Pro vyvolání určitého příkazu z historie můžete použít klávesu
322 `Ctrl-R` následovanou textem hledaného příkazu. Např:
326 * Pro rychlé kopírování textu mezi programy (např. příkazy z této stránky do shellu),
327 můžete použít prostřední tlačítko myši. Funguje to tak, že text označíte myší
328 (nemačkáte při tom Ctrl-C) a stiskem prostředního tlačítka myši v terminálovém
329 okně ho vložíte na příkazovou řádku shellu. Tím, že při tom nemusíte šahat na
330 klávesnici vám to půjde rychleji.
332 * Pokud je Qemu spouštěný přes vzdálené připojení (např. server postel),
333 je potřeba pro zobrazení emulované obrazovky spouštěného stroje
334 buď provést protunelování X protokolu (`ssh -X`) nebo používat Qemu
335 s emulací obrazovky v textovém režimu `qemu -curses`. Další možnost
336 je emulovat HW bez grafické karty `qemu -nographic` a nastavit testovaný
337 systém tak, aby systémová konzole směřovala na sériový port.
342 * [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)
343 * [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)
344 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)
345 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)
346 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
347 * [Linux Device Drivers, Third Edition][LDD3]
348 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
349 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
350 * [Rostislav Lisový: Diplomová práce - Rozšíření QEMU o podporu PCI I/O karty a tvorba ovladačů](http://rtime.felk.cvut.cz/hw/index.php/Humusoft_MF6xx)
351 * [Filip Navara: Diplomová práce - Rozšíření QEMU o podporu mikrokontroléru AT91SAM7X256](http://rtime.felk.cvut.cz/hw/index.php/AT91SAM7X256)
352 * [Aleš Kapica a další: Stránky o virtualizaci z oddělení IT K13135](https://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:QEMU)
354 [LDD3]:http://lwn.net/Kernel/LDD3/
355 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html