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_20_2
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. Knihovny, které `busybox` potřebuje ke svému běhu, zjistíte
99 ldd _install/bin/busybox
101 Na 32-bitovém systému to může vypadat například takto:
103 linux-gate.so.1 => (0xffffe000)
104 libm.so.6 => /lib/i686/cmov/libm.so.6 (0xf777c000)
105 libc.so.6 => /lib/i686/cmov/libc.so.6 (0xf7635000)
106 /lib/ld-linux.so.2 (0xf77aa000)
108 `linux-gate.so.1` (nebo `linux-vdso.so.1`) je virtuální knihovna,
109 kterou poskytuje jádro Linuxu, takže o tu se starat nemusíte.
110 Ostatní knihovny je potřeba nakopírovat do cílového systému
111 (adresáře `_install`) například následujícím způsobem:
114 cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
116 Nezapomeňte, že v cílovém filesystému musí být i tzv. interpretr
117 (`ld-linux`), který je na **64-bitovém systému v adresáři
120 Nyní už můžete spustit BusyBox v chroot prostředí.
122 5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
123 uživatelského prostředí je uložit ho ve formátu pro Linuxový
124 startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
126 Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
127 RAM-disk obsahovat i několik položek v adresáři `/dev` pro přístup
128 k virtuálním terminálům.
130 1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
132 mkdir _install/{dev,etc,proc,sys}
133 sudo cp -a /dev/tty? _install/dev
134 ln -s bin/busybox _install/init
135 (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
137 2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
138 [gen_init_cpio][gic].
143 nod /dev/tty0 644 0 0 c 4 0
144 nod /dev/tty1 644 0 0 c 4 1
145 nod /dev/tty2 644 0 0 c 4 2
146 nod /dev/tty3 644 0 0 c 4 3
147 nod /dev/tty4 644 0 0 c 4 4
148 slink /init bin/busybox 700 0 0
153 find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
154 find _install -type f -printf "file /%P %p %m 0 0\n"
155 find _install -type l -printf "slink /%P %l %m 0 0\n"
158 gen_init_cpio filelist | gzip > ramdisk
160 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD
162 5. **Jádro Linuxu**. Příprava jádra je téměř stejná jako u BusyBoxu:
163 stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
164 rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
165 trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
168 Pokud byste si chtěli přeložit vlastní jádro, v následujícím
169 příkazu byste za parametrem *-kernel* uvedli cestu k vámi
170 zkompilovanému jádru.
172 6. Bootování jádra s naším filesystémem (v emulátoru):
174 Na 64-bitovém systému spustíme emulátor následovně:
176 qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
178 Na 32-bitovém systému většinou stačí zkrácený název `qemu`:
180 qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
182 Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
183 použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
185 kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
187 [kvm]:http://www.linux-kvm.org/
189 7. Pokud vše proběhlo správně, zobrazila se hláška
191 Please press Enter to activate this console.
193 Po stisku Enteru se spustí shell a můžete začít pracovat ve
194 vašem právě vytvořeném systému.
199 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
200 zjednodušit další práci.
202 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
203 jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
204 emulátoru, ne na vaší pracovní stanici.
206 mount -t proc none /proc
208 2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
209 obsahovat příkazy, které budou spuštěny při bootu systému.
211 mkdir -p _install/etc/init.d
212 cat <<EOF > _install/etc/init.d/rcS
214 mount -t proc none /proc
217 chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
219 Nyní musíte znovu vytvořit RAM-disk a nabootovat.
221 3. Zachytávání zpráv jádra spuštěného v emulátoru QEMU do souboru
222 je možné jejich přesměrování na virtuální sériový port.
223 Požadavek na jeho vytvoření se předá QEMU zadáním parametru
225 qemu -serial file:/tmp/virtual_guest.log ...
227 a jádro spustíme s parametrem `console=ttyS0`
229 qemu -serial file:/tmp/virtual_guest.log -append console=ttyS0 ...
231 4. Pokud chcete z vašeho systému komunikovat po síti, připojte ho na
232 vnější síť s využitím NAT na uživatelské úrovni:
234 qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
236 5. Pokud QEMU nebo KVM podporuje vytvoření virtio sítě Plan9 a virtuálního
237 souborového systému, tak je možné propagovat do vnitřního systému
238 obsah adresáře hostitelského systému:
240 qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
242 Adresářovou strukturu lze z vnitřního systému připojit následujícími
249 modprobe 9pnet_virtio
251 mkdir -p /mnt/shareddir
252 mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
254 Další tipy a triky v oblasti virtualizace používané a odzkoušené zprávci
255 sítě na naší katedře nalezente na [Wiki Technické Podpory (support)][support-qemu].
256 [support-qemu]:http://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:Virtualiza%C4%8Dn%C3%AD_stroje
261 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
262 Linuxového jádra. Pokud bychom chtěli nalézt analogickou věc v
263 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
264 modul může obsahovat kód ovladače zařízení, podporu určitého
265 souborového systému, může přidávat do jádra nové funkce (např.
266 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
269 Zdrojový kód jednoduchého jaderného modulu vypadá následovně:
271 #include <linux/init.h>
272 #include <linux/module.h>
273 MODULE_LICENSE("Dual BSD/GPL");
275 static int hello_init(void)
277 printk(KERN_ALERT "Hello, world\n");
281 static void hello_exit(void)
283 printk(KERN_ALERT "Goodbye, cruel world\n");
286 module_init(hello_init);
287 module_exit(hello_exit);
288 *Příklad převzat z [LDD3][LDD3].*
290 Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
291 bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
292 soubor se jmenuje **khello.c**):
296 Nyní stačí zavolat `make` se správnými parametry:
298 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
300 Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
301 zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
302 můžete zjisti pomocí `readlink -f /lib/modules/$(uname -r)/build`),
303 pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
304 adresáři a slovo `modules` na konci znamená, že chcete, aby se
305 zkompilovaly pouze moduly.
307 Pokud vše dopadlo dobře, objevil se vám soubor `khello.ko`, což je
308 modul, který můžete zavést do jádra příkazem
317 Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
318 vaše jméno (objeví se ve výstupu příkazu `dmesg`). Jinak nemusí dělat nic.
319 Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
322 Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
323 objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
324 který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
325 v [tomto článku][henson_drivers] (strany 2 a 3).
330 * Pro vyvolání určitého příkazu z historie můžete použít klávesu
331 `Ctrl-R` následovanou textem hledaného příkazu. Např:
335 * Pro rychlé kopírování textu mezi programy (např. příkazy z této stránky do shellu),
336 můžete použít prostřední tlačítko myši. Funguje to tak, že text označíte myší
337 (nemačkáte při tom Ctrl-C) a stiskem prostředního tlačítka myši v terminálovém
338 okně ho vložíte na příkazovou řádku shellu. Tím, že při tom nemusíte šahat na
339 klávesnici vám to půjde rychleji.
341 * Pokud je Qemu spouštěný přes vzdálené připojení (např. server postel),
342 je potřeba pro zobrazení emulované obrazovky spouštěného stroje
343 buď provést protunelování X protokolu (`ssh -X`) nebo používat Qemu
344 s emulací obrazovky v textovém režimu `qemu -curses`. Další možnost
345 je emulovat HW bez grafické karty `qemu -nographic` a nastavit testovaný
346 systém tak, aby systémová konzole směřovala na sériový port
347 (`-append console=ttyS0`).
352 * [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)
353 * [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)
354 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)
355 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)
356 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
357 * [Linux Device Drivers, Third Edition][LDD3]
358 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
359 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
360 * [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)
361 * [Filip Navara: Diplomová práce - Rozšíření QEMU o podporu mikrokontroléru AT91SAM7X256](http://rtime.felk.cvut.cz/hw/index.php/AT91SAM7X256)
362 * [Aleš Kapica a další: Stránky o virtualizaci z oddělení IT K13135](https://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:QEMU)
364 [LDD3]:http://lwn.net/Kernel/LDD3/
365 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html
367 <!-- TODO pro pristi rok: At si najdou kde stahnout busybox sami.
368 Zakladni uloha jen za 3 body, za dalsi dva body uloha bez navodu: dame
369 jim binarku, ktera bude chctit sdilenou knihovnu a tu budou muset