]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2.mdwn
Remove confusing description of dynamic libraries on 64 bit system
[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. 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    Nezapomeňte, že v cílovém filesystému musí být i tzv. interpreter (`ld-linux`), který je na 64-bitovém systému v adresáři  `/lib64`.
107
108    Nyní už můžete spustit BusyBox v chroot prostředí.
109
110 5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
111    uživatelského prostředí je uložit ho ve formátu pro Linuxový
112    startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
113    
114    Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
115    RAM-disk obsahovat i několik položek v adresáři `/dev` pro přístup k
116    virtuálním terminálům.
117
118    1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
119
120           mkdir _install/{dev,etc,proc,sys}
121           sudo cp -a /dev/tty? _install/dev
122           ln -s bin/busybox _install/init
123           (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
124
125    2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
126       [gen_init_cpio][gic].
127
128           (
129           cat <<EOF
130           dir /dev 755 0 0
131           nod /dev/tty0 644 0 0 c 4 0
132           nod /dev/tty1 644 0 0 c 4 1
133           nod /dev/tty2 644 0 0 c 4 2
134           nod /dev/tty3 644 0 0 c 4 3
135           nod /dev/tty4 644 0 0 c 4 4
136           slink /init bin/busybox 700 0 0
137           dir /proc 755 0 0
138           dir /sys 755 0 0
139           EOF
140             
141           find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
142           find _install -type f -printf "file /%P %p %m 0 0\n"
143           find _install -type l -printf "slink /%P %l %m 0 0\n"
144           ) > filelist
145             
146           gen_init_cpio filelist | gzip > ramdisk
147
148 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD      
149
150 5. **Jádro Linuxu**. Příprava jádra je téměř stejná jako u BusyBoxu:
151    stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
152    rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
153    trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
154    jádro z distribuce.
155    
156    Pokud byste si chtěli přeložit vlastní jádro, v následujícím
157    příkazu byste za parametrem *-kernel* uvedli cestu k vámi
158    zkompilovanému jádru.
159
160 6. Bootování jádra s naším filesystémem (v emulátoru):
161
162    Na 64-bitovém systému spustíme emulátor následovně:
163
164        qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
165
166    Na 32-bitovém systému většinou stačí zkrácený název `qemu`:
167
168        qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
169
170    Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
171    použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
172
173        kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
174
175 [kvm]:http://www.linux-kvm.org/ 
176
177 7. Pokud vše proběhlo správně, zobrazila se hláška
178
179        Please press Enter to activate this console.
180     
181    Po stisku Enteru se spustí shell a můžete začít pracovat ve
182    vašem právě vytvořeném systému.
183    
184 Možná vylepšení
185 ===============
186
187 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
188 zjednodušit další práci.
189
190 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
191    jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
192    emulátoru, ne na vaší pracovní stanici.
193
194        mount -t proc none /proc
195
196 2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
197    obsahovat příkazy, které budou spuštěny při bootu systému.
198
199        mkdir -p _install/etc/init.d
200        cat <<EOF > _install/etc/init.d/rcS
201        #!/bin/sh
202        mount -t proc none /proc
203        echo Nazdar!!!!
204        EOF
205        chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
206
207    Nyní musíte znovu vytvořit RAM-disk a nabootovat.
208
209 3. Zachytávání zpráv jádra spuštěného v emulátoru QEMU do souboru
210    je možné jejich přesměrování na virtuální sériový port.
211    Požadavek na jeho vytvoření se předá QEMU zadáním parametru
212
213        qemu -serial file:/tmp/virtual_guest.log ...
214
215    a jádro spustíme s parametrem `console=ttyS0`
216
217        qemu -serial file:/tmp/virtual_guest.log -append console=ttyS0 ...
218
219 4. Pokud chcete z vašeho systému komunikovat po síti, připojte ho na
220    vnější síť s využitím NAT na uživatelské úrovni:
221
222        qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
223
224 5. Pokud QEMU nebo KVM podporuje vytvoření virtio sítě Plan9 a virtuálního
225    souborového systému, tak je možné propagovat do vnitřního systému
226    obsah adresáře hostitelského systému:
227
228        qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
229
230    Adresářovou strukturu lze z vnitřního systému připojit následujícími
231    příkazy
232
233        modprobe virtio
234            modprobe virtio_ring
235            modprobe virtio_pci
236            modprobe 9pnet
237            modprobe 9pnet_virtio
238            modprobe 9p
239            mkdir -p /mnt/shareddir
240            mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
241
242 Další tipy a triky v oblasti virtualizace používané a odzkoušené zprávci
243 sítě na naší katedře nalezente na [Wiki Technické Podpory (support)][support-qemu].
244 [support-qemu]:http://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:Virtualiza%C4%8Dn%C3%AD_stroje
245
246 Jaderné moduly
247 ==============
248
249 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
250 Linuxového jádra. Pokud bychom chtěli nalézt analogickou věc v
251 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
252 modul může obsahovat kód ovladače zařízení, podporu určitého
253 souborového systému, může přidávat do jádra nové funkce (např.
254 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
255 (např. libata).
256
257 Zdrojový kód jednoduchého jaderného modulu vypadá následovně: 
258
259     #include <linux/init.h>
260     #include <linux/module.h>
261     MODULE_LICENSE("Dual BSD/GPL");
262     
263     static int hello_init(void)
264     {
265         printk(KERN_ALERT "Hello, world\n");
266         return 0;
267     }
268     
269     static void hello_exit(void)
270     {
271         printk(KERN_ALERT "Goodbye, cruel world\n");
272     }
273     
274     module_init(hello_init);
275     module_exit(hello_exit);
276 *Příklad převzat z [LDD3][LDD3].*
277
278 Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
279 bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
280 soubor se jmenuje **khello.c**):
281
282     obj-m = khello.o
283
284 Nyní stačí zavolat `make` se správnými parametry:
285
286     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
287
288 Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
289 zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
290 můžete zjisti pomocí `readlink -f /lib/modules/$(uname -r)/build`),
291 pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
292 adresáři a slovo `modules` na konci znamená, že chcete, aby se
293 zkompilovaly pouze moduly.
294
295 Pokud vše dopadlo dobře, objevil se vám soubor `khello.ko`, což je
296 modul, který můžete zavést do jádra příkazem
297
298     insmod khello.ko
299
300
301
302 Zadání
303 ======
304
305 Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
306 vaše jméno (objeví se ve výstupu příkazu `dmesg`). Jinak nemusí dělat nic.
307 Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
308 emulátoru.
309
310 Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
311 objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
312 který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
313 v [tomto článku][henson_drivers] (strany 2 a 3).
314
315 Tipy a triky
316 ============
317
318 * Pro vyvolání určitého příkazu z historie můžete použít klávesu
319   `Ctrl-R` následovanou textem hledaného příkazu. Např:
320
321       <Ctrl-R>cpio<Enter>
322
323 * Pro rychlé kopírování textu mezi programy (např. příkazy z této stránky do shellu),
324   můžete použít prostřední tlačítko myši. Funguje to tak, že text označíte myší
325   (nemačkáte při tom Ctrl-C) a stiskem prostředního tlačítka myši v terminálovém
326   okně ho vložíte na příkazovou řádku shellu. Tím, že při tom nemusíte šahat na
327   klávesnici vám to půjde rychleji.
328
329 * Pokud je Qemu spouštěný přes vzdálené připojení (např. server postel),
330   je potřeba pro zobrazení emulované obrazovky spouštěného stroje
331   buď provést protunelování X protokolu (`ssh -X`) nebo používat Qemu
332   s emulací obrazovky v textovém režimu `qemu -curses`. Další možnost
333   je emulovat HW bez grafické karty `qemu -nographic` a nastavit testovaný
334   systém tak, aby systémová konzole směřovala na sériový port
335   (`-append console=ttyS0`).
336
337 Reference
338 =========
339
340 * [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)
341 * [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)
342 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)  
343 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)  
344 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
345 * [Linux Device Drivers, Third Edition][LDD3]
346 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
347 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
348 * [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)
349 * [Filip Navara: Diplomová práce - Rozšíření QEMU o podporu mikrokontroléru AT91SAM7X256](http://rtime.felk.cvut.cz/hw/index.php/AT91SAM7X256)
350 * [Aleš Kapica a další: Stránky o virtualizaci z oddělení IT K13135](https://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:QEMU)
351   
352 [LDD3]:http://lwn.net/Kernel/LDD3/
353 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html