]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2.mdwn
Zajacik - nahradni test
[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_20_2
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. Knihovny, které `busybox` potřebuje ke svému běhu, zjistíte
97    příkazem
98
99        ldd _install/bin/busybox
100
101    Na 32-bitovém systému to může vypadat například takto:
102
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)
107
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:
112
113        mkdir _install/lib
114        cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
115
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
118    `/lib64`**.
119
120    Nyní už můžete spustit BusyBox v chroot prostředí.
121
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.
125    
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.
129
130    1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
131
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
136
137    2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
138       [gen_init_cpio][gic].
139
140           (
141           cat <<EOF
142           dir /dev 755 0 0
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
149           dir /proc 755 0 0
150           dir /sys 755 0 0
151           EOF
152             
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"
156           ) > filelist
157             
158           gen_init_cpio filelist | gzip > ramdisk
159
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      
161
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é
166    jádro z distribuce.
167    
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.
171
172 6. Bootování jádra s naším filesystémem (v emulátoru):
173
174    Na 64-bitovém systému spustíme emulátor následovně:
175
176        qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
177
178    Na 32-bitovém systému většinou stačí zkrácený název `qemu`:
179
180        qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
181
182    Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
183    použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
184
185        kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
186
187 [kvm]:http://www.linux-kvm.org/ 
188
189 7. Pokud vše proběhlo správně, zobrazila se hláška
190
191        Please press Enter to activate this console.
192     
193    Po stisku Enteru se spustí shell a můžete začít pracovat ve
194    vašem právě vytvořeném systému.
195    
196 Možná vylepšení
197 ===============
198
199 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
200 zjednodušit další práci.
201
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.
205
206        mount -t proc none /proc
207
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.
210
211        mkdir -p _install/etc/init.d
212        cat <<EOF > _install/etc/init.d/rcS
213        #!/bin/sh
214        mount -t proc none /proc
215        echo Nazdar!!!!
216        EOF
217        chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
218
219    Nyní musíte znovu vytvořit RAM-disk a nabootovat.
220
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
224
225        qemu -serial file:/tmp/virtual_guest.log ...
226
227    a jádro spustíme s parametrem `console=ttyS0`
228
229        qemu -serial file:/tmp/virtual_guest.log -append console=ttyS0 ...
230
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:
233
234        qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
235
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:
239
240        qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
241
242    Adresářovou strukturu lze z vnitřního systému připojit následujícími
243    příkazy
244
245        modprobe virtio
246            modprobe virtio_ring
247            modprobe virtio_pci
248            modprobe 9pnet
249            modprobe 9pnet_virtio
250            modprobe 9p
251            mkdir -p /mnt/shareddir
252            mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
253
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
257
258 Jaderné moduly
259 ==============
260
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
267 (např. libata).
268
269 Zdrojový kód jednoduchého jaderného modulu vypadá následovně: 
270
271     #include <linux/init.h>
272     #include <linux/module.h>
273     MODULE_LICENSE("Dual BSD/GPL");
274     
275     static int hello_init(void)
276     {
277         printk(KERN_ALERT "Hello, world\n");
278         return 0;
279     }
280     
281     static void hello_exit(void)
282     {
283         printk(KERN_ALERT "Goodbye, cruel world\n");
284     }
285     
286     module_init(hello_init);
287     module_exit(hello_exit);
288 *Příklad převzat z [LDD3][LDD3].*
289
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**):
293
294     obj-m = khello.o
295
296 Nyní stačí zavolat `make` se správnými parametry:
297
298     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
299
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.
306
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
309
310     insmod khello.ko
311
312
313
314 Zadání
315 ======
316
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
320 emulátoru.
321
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).
326
327 Tipy a triky
328 ============
329
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ř:
332
333       <Ctrl-R>cpio<Enter>
334
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.
340
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`).
348
349 Reference
350 =========
351
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)
363   
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
366
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
370 napsat. -->