]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2.mdwn
Nefunguje format plugin
[edu/osp-wiki.git] / cviceni / 2.mdwn
1 [[!meta title="Embedded Linux"]]
2
3 [[!toc]]
4
5 Cíl cvičení
6 ===========
7
8 Open source projekty se často nepoužívají osamoceně, ale v kombinaci s
9 jinými OSS projekty, čímž vznikají tak tzv. OSS stacky. Asi
10 nejznámějším stackem je LAMP – Linux, Apache, MySQL, PHP. Na dnešním
11 cvičení se seznámíme s dalším, velmi často používaným, stackem
12 [Linux][kenrel] + [BusyBox][bb] (+[Dropbear][dropbear] SSH server).
13
14 [BusyBox][bb] je sada UNIXových uživatelských nástrojů (shell, editor,
15 utility jako ls, mkdir, …) zkompilovaná do jedné binárky. V kombinaci
16 s jádrem Linuxu tak dostáváme kompletní operační systém s poměrně
17 malými nároky na paměť. Díky tomu se tato kombinace často používá ve
18 vestavěných (embedded) aplikacích jako například
19 [WiFi routery či ADSL modemy][owrt].
20
21 V tomto cvičení si zkusíte vytvořit kompletní open source operační
22 systém z Linuxového jádra a uživatelského prostředí tvořeného právě
23 BusyBoxem. Dále si vyzkoušíte naprogramovat jednoduchý modul do jádra.
24
25 [kenrel]: http://kernel.org/
26 [bb]:http://busybox.net/
27 [owrt]:http://www.openwrt.org/
28 [dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
29
30 Postup
31 ======
32
33 1. Stáhneme [zdrojové kódy][bbgit] projektu [BusyBox][bb]:
34
35         git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
36         cd busybox
37
38 [bbgit]:http://git.busybox.net/busybox/
39
40 2. Zkonfigurujeme jak chceme BusyBox přeložit. 
41
42         make menuconfig
43
44    Vystačíme s výchozí konfigurací, takže zvolit `Exit` a odpovědět
45    `Yes`, že chceme konfiguraci uložit.
46    
47 3. Kompilaci provedeme tradičně příkazem
48
49         make
50
51 4. Příkazem
52
53         make install
54
55     nainstalujeme busybox do adresáře `./_install`. Všimněte si, že se
56     tam nachází pouze jedna binárka `bin/busybox` a všechno ostatní
57     jsou pouze symbolické odkazy na tuto binárku.
58     
59     Protože neprovádíme tzv. *křížový překlad*, který je běžný pro v
60     případě vestavěných zařízení, můžeme výsledek hned otestovat
61     například spuštěním shellu: `./_install/bin/sh` (ukončíme ho např.
62     příkazem `exit`).
63     
64     V případě skutečného vestavěného systému bychom museli pokračovat
65     dál a bysybox otestovat až po nabootování na cílovém hardwaru.
66
67 5. Pokud máte na vašem počítači práva superuživatele root, můžete
68    otestovat BusyBox v chroot prostředí, t.j. se stejným jádrem jako
69    právě běží na vašem počítači, ale se souborovým systémem tvořeným
70    pouze BusyBoxem:
71
72         # chroot _install /bin/sh
73
74    Fungovat to ale nebude, protože ke spuštění BusyBoxu jsou potřeba
75    knihovny, které v nejsou v adresáři `_install` dostupné.
76
77 6. Chybějící knihovny zjistíte příkazem
78
79         ldd _install/bin/busybox
80         
81    Tyto knihovny musíte nakopírovat do adresáře `_install`
82
83         mkdir _install/lib
84         cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
85
86    Nyní už můžete spustit BusyBox v chroot prostředí.
87
88 5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
89    uživatelského prostředí je uložit ho ve formátu pro Linuxový
90    startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
91    
92    Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
93    RAM-disk obsahovat i někoik položek v adresáři `/dev` pro přístup k
94    virtuálním terminálům.
95
96    1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
97
98             mkdir _install/{dev,etc,proc,sys}
99             sudo cp -a /dev/tty? _install/dev
100             ln -s bin/busybox _install/init
101             (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
102
103    2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástoje
104       [gen_init_cpio][gic].
105
106             (
107             cat <<EOF
108             dir /dev 755 0 0
109             nod /dev/tty0 644 0 0 c 4 0
110             nod /dev/tty1 644 0 0 c 4 1
111             nod /dev/tty2 644 0 0 c 4 2
112             nod /dev/tty3 644 0 0 c 4 3
113             nod /dev/tty4 644 0 0 c 4 4
114             slink /init bin/busybox 700 0 0
115             dir /proc 755 0 0
116             dir /sys 755 0 0
117             EOF
118             
119             find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
120             find _install -type f -printf "file /%P %p %m 0 0\n"
121             find _install -type l -printf "slink /%P %l %m 0 0\n"
122             ) > filelist
123             
124             gen_init_cpio filelist > ramdisk
125
126 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD      
127
128 5. **Jádro Linuxu**. Příprava jádra je téměř stejná jako u BusyBoxu:
129    stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
130    rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
131    trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
132    jádro z distribuce.
133    
134    Pokud byste si chtěli přeložit vlastní jádro, v následujícím
135    příkazu byste za parametrem *-kernel* uvedli cestu k vámi
136    zkompilovanému jádru.
137
138 6. Bootování jádra s naším filesystémem (v emulátoru):
139
140         qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
141
142 7. Pokud vše proběhlo správně, zobrazila se hláška
143
144         Please press Enter to activate this console.
145     
146    Po stisku Enteru se spustí shell a můžete začít pracovat ve
147    vašem právě vytvořeném systému.
148    
149 Možná vylepšení
150 ===============
151
152 Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
153 zjednodušit další práci.
154
155 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
156    jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
157    emulátoru, ne na vaší pracovní stanici.
158
159         mount -t proc none /proc
160
161 2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
162    obsahovat příkazy, které budou spuštěny při bootu systému.
163
164         mkdir -p _install/etc/init.d
165         cat <<EOF > _install/etc/init.d/rcS
166         #!/bin/sh
167         mount -t proc none /proc
168         echo Nazdar!!!!
169         EOF
170         chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
171
172    Nyní musíte znovu vytvořit RAM-disk a nabootovat.
173
174 Jaderné moduly
175 ==============
176
177 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
178 Linuxvého jádra. Pokud bychom chtěli nalézt analogickou věc v
179 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
180 modul může obsahovat kód ovladače zařízení, podporu určitého
181 souborového systému, může přidávat do jádra nové funkce (např.
182 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
183 (např. libata).
184
185 Zdrojový kód jednoduchého jaderného modulu vypadá následovně: 
186
187     #include <linux/init.h>
188     #include <linux/module.h>
189     MODULE_LICENSE("Dual BSD/GPL");
190     
191     static int hello_init(void)
192     {
193         printk(KERN_ALERT "Hello, world\n");
194         return 0;
195     }
196     
197     static void hello_exit(void)
198     {
199         printk(KERN_ALERT "Goodbye, cruel world\n");
200     }
201     
202     module_init(hello_init);
203     module_exit(hello_exit);
204 *Příklad převzat z [LDD3][LDD3].*
205
206 Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
207 bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
208 soubor se jmenuje khello.c):
209
210     obj-m = khello.o
211
212 Nyní stačí zavolat `make` se správnými parametry:
213
214     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
215
216 Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
217 zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
218 můžete zjistít pomocí `readlink -f /lib/modules/$(uname -r)/build`),
219 pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
220 adresáři a slovo `modules` na konci znamená, že chcete, aby se
221 zkompilovaly pouze moduly.
222
223 Pokud vše dopadlo dobře, objevil se vám soubor `khello.ko`, což je
224 modul, který můžete zavést do jádra příkazem
225
226     insmod khello.ko
227
228
229
230 Zadání
231 ======
232
233 Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
234 vaše jméno (objeví se ve výstupu `dmesg`). Jinak nemusí dělat nic.
235 Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
236 emulátoru.
237
238 Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
239 objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
240 který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
241 v [tomto článku][henson_drivers] (strany 2 a 3).
242
243 Tipy a triky
244 ============
245
246 * Pro vyvolání určitého příkazu z historie můžete použít klávesu
247   `Ctrl-R` následovanou textem hledaného příkazu. Např:
248
249         <Ctrl-R>cpio<Enter>
250
251 Reference
252 =========
253
254 * [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)
255 * [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)
256 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)  
257 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)  
258 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
259 * [Linux Device Drivers, Third Edition][LDD3]
260 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
261 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
262   
263 [LDD3]:http://lwn.net/Kernel/LDD3/
264 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html