]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2.mdwn
Fix indentation etc
[edu/osp-wiki.git] / cviceni / 2.mdwn
1 [[!meta title="Embedded Linux"]]
2
3 [[!toc]]
4
5 Cíl cvičení
6 ===========
7
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.
13
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
19 server).
20
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].
27
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.
31
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
36
37 Postup
38 ======
39
40 1. Stáhneme [zdrojové kódy][bbgit] projektu [BusyBox][bb]:
41
42        git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
43        cd busybox
44
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
48
49        gitk
50
51     a můžeme si vybrat verzi, kde se chyba nevyskytuje. Například
52
53        git checkout -f 1_18_3
54
55 [bbgit]:http://git.busybox.net/busybox/
56
57 2. Zkonfigurujeme jak chceme BusyBox přeložit. 
58
59        make menuconfig
60
61    Vystačíme s výchozí konfigurací, takže zvolte `Exit` a odpovězte
62    `Yes`, že chcete konfiguraci uložit.
63    
64 3. Kompilaci provedeme tradičně příkazem
65
66        make
67
68 4. Příkazem
69
70        make install
71
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.
75     
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`).
80     
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.
83
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
87    pouze BusyBoxem:
88
89        # chroot _install /bin/sh
90
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é.
93    
94 [chroot]:http://en.wikipedia.org/wiki/Chroot
95
96 6. Chybějící knihovny zjistíte příkazem
97
98        ldd _install/bin/busybox
99         
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:
102
103        mkdir _install/lib
104        cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
105
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`
109
110        ( cd _install && ln -s lib lib64 )
111
112    Nyní už můžete spustit BusyBox v chroot prostředí.
113
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.
117    
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.
121
122    1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
123
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
128
129    2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
130       [gen_init_cpio][gic].
131
132           (
133           cat <<EOF
134           dir /dev 755 0 0
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
141           dir /proc 755 0 0
142           dir /sys 755 0 0
143           EOF
144             
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"
148           ) > filelist
149             
150           gen_init_cpio filelist | gzip > ramdisk
151
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      
153
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é
158    jádro z distribuce.
159    
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.
163
164 6. Bootování jádra s naším filesystémem (v emulátoru):
165
166     Na 32-bitovém systému spustíme emulátor následovně:
167
168         qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
169
170     Na 64-bitovém systému může být potřeba použít příslušnou variantu QEMU:
171
172         qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
173
174     Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
175     použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
176
177         kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
178
179 [kvm]:http://www.linux-kvm.org/ 
180
181 7. Pokud vše proběhlo správně, zobrazila se hláška
182
183         Please press Enter to activate this console.
184     
185    Po stisku Enteru se spustí shell a můžete začít pracovat ve
186    vašem právě vytvořeném systému.
187    
188 Možná vylepšení
189 ===============
190
191 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
192 zjednodušit další práci.
193
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.
197
198         mount -t proc none /proc
199
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.
202
203         mkdir -p _install/etc/init.d
204         cat <<EOF > _install/etc/init.d/rcS
205         #!/bin/sh
206         mount -t proc none /proc
207         echo Nazdar!!!!
208         EOF
209         chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
210
211    Nyní musíte znovu vytvořit RAM-disk a nabootovat.
212
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
216
217         qemu -serial file:/tmp/virtual_guest.log ...
218
219    a jádro spustíme s parametrem `console=ttyS0`
220
221         qemu -serial file:/tmp/virtual_guest.log -append console=ttyS0 ...
222
223 4. Připojení virtuálního stroje na vější síť s využitím NAT na uživatelské úrovni.
224
225         qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
226
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
230
231         qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
232
233    Adresářovou strukturu lze z vnitřního systému připojit následujícími
234    příkazy
235
236         modprobe virtio
237         modprobe virtio_ring
238         modprobe virtio_pci
239         modprobe 9pnet
240         modprobe 9pnet_virtio
241         modprobe 9p
242         mkdir -p /mnt/shareddir
243         mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
244
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
248
249 Jaderné moduly
250 ==============
251
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
258 (např. libata).
259
260 Zdrojový kód jednoduchého jaderného modulu vypadá následovně: 
261
262     #include <linux/init.h>
263     #include <linux/module.h>
264     MODULE_LICENSE("Dual BSD/GPL");
265     
266     static int hello_init(void)
267     {
268         printk(KERN_ALERT "Hello, world\n");
269         return 0;
270     }
271     
272     static void hello_exit(void)
273     {
274         printk(KERN_ALERT "Goodbye, cruel world\n");
275     }
276     
277     module_init(hello_init);
278     module_exit(hello_exit);
279 *Příklad převzat z [LDD3][LDD3].*
280
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**):
284
285     obj-m = khello.o
286
287 Nyní stačí zavolat `make` se správnými parametry:
288
289     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
290
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 zjistít 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.
297
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
300
301     insmod khello.ko
302
303
304
305 Zadání
306 ======
307
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
311 emulátoru.
312
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).
317
318 Tipy a triky
319 ============
320
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ř:
323
324         <Ctrl-R>cpio<Enter>
325
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.
331
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.
338
339 Reference
340 =========
341
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)
353   
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