===========
Cílem tohoto cvičení je prakticky si procvičit informace probírané na
-2. přednášce a motivovat vás ke 4. přednášce "*Linuxové jádro - vznik,
+2. přednášce a motivovat vás ke 4. přednášce "*Linuxové jádro – vznik,
vývoj, skladba a ovladače; GNU libc a uživatelský prostor*". Pokud vám
nejsou jasné některé souvislosti, doporučujeme zkusit si informace
vygooglovat a připravit si otázky na 4. přednášku.
Open source software (OSS) projekty se často nepoužívají osamoceně,
-ale v kombinaci s jinými OSS projekty, čímž vznikají tak tzv. OSS
+ale v kombinaci s jinými OSS projekty, čímž vznikají tak tzv. OSS
stacky. Asi nejznámějším stackem je LAMP – Linux, Apache, MySQL, PHP.
-Na dnešním cvičení se seznámíme s dalším, velmi často používaným,
-stackem [Linux][kenrel] + [BusyBox][bb] (+[Dropbear][dropbear] SSH
-server).
+Na dnešním cvičení se seznámíme s dalším, velmi často používaným,
+stackem [Linux][] + [BusyBox][] (+[Dropbear][] SSH server).
-[BusyBox][bb] je sada UNIXových uživatelských nástrojů (shell, editor,
-utility jako ls, mkdir, …) zkompilovaná do jedné binárky. V kombinaci
-s jádrem Linuxu tak dostáváme kompletní operační systém s poměrně
+[BusyBox][] je sada UNIXových uživatelských nástrojů (shell, editor,
+utility jako ls, mkdir, …) zkompilovaná do jedné binárky. V kombinaci
+s jádrem Linuxu tak dostáváme kompletní operační systém s poměrně
malými nároky na paměť. Díky tomu se tato kombinace často používá ve
vestavěných (embedded) aplikacích jako například
[WiFi routery či ADSL modemy][owrt].
-V tomto cvičení si zkusíte vytvořit kompletní open source operační
-systém z Linuxového jádra a uživatelského prostředí tvořeného právě
+V tomto cvičení si zkusíte vytvořit kompletní open source operační
+Systém z Linuxového jádra a uživatelského prostředí tvořeného právě
BusyBoxem. Dále si vyzkoušíte naprogramovat jednoduchý modul do jádra.
-[kenrel]: http://kernel.org/
-[bb]:http://busybox.net/
+[Linux]: http://kernel.org/
+[BusyBox]:http://busybox.net/
[owrt]:http://www.openwrt.org/
-[dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
+[Dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
Postup
======
-1. Stáhneme [zdrojové kódy][bbgit] projektu [BusyBox][bb]:
+1. Stáhněte si zdrojové kódy z git repozitáře projektu [BusyBox][]
+ (adresu repozitáře si najděte sami).
- git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
- cd busybox
+ git clone ...
+ cd busybox
Protože se jedná o aktuální vývojový snapshot, je možné, že se
při překladu, instalaci nebo používání vyskytne chyba. Naší výhodou
- však je, že máme k dispozici kompletní historii projektu
+ však je, že máme k dispozici kompletní historii projektu
- qgit
+ gitk
a můžeme si vybrat verzi, kde se chyba nevyskytuje. Například
- git checkout -f 1_18_3
-
-[bbgit]:http://git.busybox.net/busybox/
+ git checkout -f 1_22_0
2. Zkonfigurujeme jak chceme BusyBox přeložit.
- make menuconfig
+ make menuconfig
- Vystačíme s výchozí konfigurací, takže zvolit `Exit` a odpovědět
- `Yes`, že chceme konfiguraci uložit.
+ Vystačíme s výchozí konfigurací, takže zvolte `Exit` a odpovězte
+ `Yes`, že chcete konfiguraci uložit.
3. Kompilaci provedeme tradičně příkazem
- make
+ make
4. Příkazem
- make install
+ make install
- nainstalujeme busybox do adresáře `./_install`. Všimněte si, že se
- tam nachází pouze jedna binárka `bin/busybox` a všechno ostatní
- jsou pouze symbolické odkazy na tuto binárku.
+ nainstalujeme busybox do adresáře `./_install`. Všimněte si (`ls
+ -lR _install`), že se tam nachází pouze jedna binárka `bin/busybox`
+ a všechno ostatní jsou pouze symbolické odkazy na tuto binárku.
- Protože neprovádíme tzv. *křížový překlad*, který je běžný v
- případě vestavěných zařízení, můžeme výsledek hned otestovat
- například spuštěním shellu: `./_install/bin/sh` (ukončíme ho např.
- příkazem `exit`).
+ Protože neprovádíme tzv. *křížový překlad* (cross compilation),
+ který je běžný v případě vestavěných zařízení, můžeme výsledek
+ hned otestovat například spuštěním shellu: `./_install/bin/sh`
+ (ukončíme ho např. příkazem `exit`).
- V případě skutečného vestavěného systému bychom museli pokračovat
+ V případě skutečného vestavěného systému bychom museli pokračovat
dál a busybox otestovat až po nabootování na cílovém hardwaru.
-5. Pokud máte na vašem počítači práva superuživatele root, můžete
- otestovat BusyBox v [chroot prostředí][chroot], t.j. se stejným jádrem jako
+5. Pokud máte na svém počítači práva uživatele `root`, můžete
+ otestovat BusyBox v [chroot prostředí][chroot], t.j. se stejným jádrem jako
právě běží na vašem počítači, ale se souborovým systémem tvořeným
pouze BusyBoxem:
- # chroot _install /bin/sh
+ # chroot _install /bin/sh
Fungovat to ale nebude, protože ke spuštění BusyBoxu jsou potřeba
- knihovny, které v nejsou v adresáři `_install` dostupné.
+ knihovny, které v nejsou v adresáři `_install` dostupné.
[chroot]:http://en.wikipedia.org/wiki/Chroot
-6. Chybějící knihovny zjistíte příkazem
+6. Knihovny, které `busybox` potřebuje ke svému běhu, zjistíte
+ příkazem
+
+ ldd _install/bin/busybox
+
+ Na 32-bitovém systému to může vypadat například takto:
- ldd _install/bin/busybox
-
- Tyto knihovny musíte nakopírovat do adresáře `_install`. Na
- 32-bitovém systému to může vypadat například takto:
+ linux-gate.so.1 => (0xffffe000)
+ libm.so.6 => /lib/i686/cmov/libm.so.6 (0xf777c000)
+ libc.so.6 => /lib/i686/cmov/libc.so.6 (0xf7635000)
+ /lib/ld-linux.so.2 (0xf77aa000)
- mkdir _install/lib
- cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
+ `linux-gate.so.1` (nebo `linux-vdso.so.1`) je virtuální knihovna,
+ kterou poskytuje jádro Linuxu, takže o tu se starat nemusíte.
+ Ostatní knihovny je potřeba nakopírovat do cílového systému
+ (adresáře `_install`) například následujícím způsobem:
- Na 64-bitovém systému jádro hledá pro dynamicky linkované programy
- "interpreter" `/lib64/ld-linux-x86-64.so.2` v adresáři `/lib64`.
- Vytvoříme ho jako symbolický odkaz na adresář `/lib`
+ mkdir _install/lib
+ cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
- ( cd _install && ln -s lib lib64 )
+ Nezapomeňte, že v cílovém filesystému musí být i tzv. interpretr
+ (`ld-linux`), který je na **64-bitovém systému v adresáři
+ `/lib64`**.
- Nyní už můžete spustit BusyBox v chroot prostředí.
+ Nyní už můžete spustit BusyBox v chroot prostředí.
5. Nejjednodušší možnost jak nabootovat do právě vytvořeného
uživatelského prostředí je uložit ho ve formátu pro Linuxový
- startovací RAM-disk a nabootovat Linux s tímto RAM-diskem.
+ startovací RAM-disk a nabootovat Linuxové jádro s tímto RAM-diskem.
- Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
- RAM-disk obsahovat i několik položek v adresáři `/dev` pro přístup k
- virtuálním terminálům.
+ Aby vše fungovalo jak má, kromě souborů v adresáři `_install` musí
+ RAM-disk obsahovat i několik položek v adresáři `/dev` pro přístup
+ k virtuálním terminálům. V závislosti na vašem oprávnění můžete
+ RAM-disk vytvořit jedním z následujících způsobů:
- 1. Pokud máte root práva, použijte ke tvorbě RAM-disku následující příkazy:
+ 1. Pokud máte *rootovská* práva, použijte ke tvorbě RAM-disku
+ následující příkazy:
- mkdir _install/{dev,etc,proc,sys}
- sudo cp -a /dev/tty? _install/dev
- ln -s bin/busybox _install/init
- (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
+ mkdir _install/{dev,etc,proc,sys}
+ sudo cp -a /dev/tty? _install/dev
+ ln -s bin/busybox _install/init
+ (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
2. Bez rootovských práv můžete RAM-disk vytvořit pomocí nástroje
- [gen_init_cpio][gic].
-
- (
- cat <<EOF
- dir /dev 755 0 0
- nod /dev/tty0 644 0 0 c 4 0
- nod /dev/tty1 644 0 0 c 4 1
- nod /dev/tty2 644 0 0 c 4 2
- nod /dev/tty3 644 0 0 c 4 3
- nod /dev/tty4 644 0 0 c 4 4
- slink /init bin/busybox 700 0 0
- dir /proc 755 0 0
- dir /sys 755 0 0
- EOF
+ [gen_init_cpio][gic]. Pokud program nemáte na svém počítači,
+ zkompilujte si ho ze [zdrojových kódů][gic].
+
+ (
+ cat <<EOF
+ dir /dev 755 0 0
+ nod /dev/tty0 644 0 0 c 4 0
+ nod /dev/tty1 644 0 0 c 4 1
+ nod /dev/tty2 644 0 0 c 4 2
+ nod /dev/tty3 644 0 0 c 4 3
+ nod /dev/tty4 644 0 0 c 4 4
+ slink /init bin/busybox 700 0 0
+ dir /proc 755 0 0
+ dir /sys 755 0 0
+ EOF
- find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
- find _install -type f -printf "file /%P %p %m 0 0\n"
- find _install -type l -printf "slink /%P %l %m 0 0\n"
- ) > filelist
+ find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
+ find _install -type f -printf "file /%P %p %m 0 0\n"
+ find _install -type l -printf "slink /%P %l %m 0 0\n"
+ ) > filelist
- gen_init_cpio filelist | gzip > ramdisk
+ gen_init_cpio filelist | gzip > ramdisk
+
+ Výše uvedené příkazy fungují následovně: Nejprve vytvoříme
+ seznam souborů (`filelist`), které má ramdisk obsahovat. Nástroj
+ `gen_init_cpio` pak podle toho seznamu vytvoří obraz ramdisku,
+ který "zazipujeme" příkazem `gzip` a uložíme do souboru
+ `ramdisk`.
[gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD
stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
- jádro z distribuce.
+ jádro z distribuce.
- Pokud byste si chtěli přeložit vlastní jádro, v následujícím
- příkazu byste za parametrem *-kernel* uvedli cestu k vámi
+ Pokud byste si chtěli přeložit vlastní jádro, v následujícím
+ příkazu byste za parametrem *-kernel* uvedli cestu k vámi
zkompilovanému jádru.
-6. Bootování jádra s naším filesystémem (v emulátoru):
+6. Bootování jádra s naším filesystémem (v softwarovém emulátoru
+ systému):
- Na 32-bitovém systému spustíme emulátor následovně:
+ Na 64-bitovém systému spustíme emulátor následovně:
- qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
+ qemu-system-x86_64 -kernel /boot/vmlinuz-3.2.0-4-amd64 -initrd ramdisk
- Na 64-bitovém systému může být potřeba použít příslušnou variantu QEMU:
+ Na 32-bitovém systému použijte:
- qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
+ qemu-system-i386 -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
- Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
- použít [KVM][kvm]. Výsledek pak běží rychleji. Například:
+ Pokud systém nabízí hardwarovou podporu virtualizace, je výhodné
+ použít virtualizační nástroj [KVM][kvm]. Výsledek pak běží
+ rychleji. KVM vychází z qemu a má tudíž téměř stejné parametry
+ příkazové řádky. Například:
- kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
+ kvm -kernel /boot/vmlinuz-3.2.0-4-amd64 -initrd ramdisk
[kvm]:http://www.linux-kvm.org/
7. Pokud vše proběhlo správně, zobrazila se hláška
- Please press Enter to activate this console.
+ Please press Enter to activate this console.
Po stisku Enteru se spustí shell a můžete začít pracovat ve
vašem právě vytvořeném systému.
Možná vylepšení
===============
-Dále můžete provést drobná vylepšení vašeho systému, která vám mohou
-zjednodušit další práci.
+Dále můžete provést drobná (či větší) vylepšení svého nového systému,
+která vám mohou zjednodušit další práci.
1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
- jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
- emulátoru, ne na vaší pracovní stanici.
+ jako např. `ps` (výpis běžících procesů). Příkaz spusťte
+ v emulátoru, ne na vaší pracovní stanici.
- mount -t proc none /proc
+ mount -t proc none /proc
-2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
+2. V RAM-disku můžete vytvořit soubor `/etc/init.d/rcS`, který bude
obsahovat příkazy, které budou spuštěny při bootu systému.
- mkdir -p _install/etc/init.d
- cat <<EOF > _install/etc/init.d/rcS
- #!/bin/sh
- mount -t proc none /proc
- echo Nazdar!!!!
- EOF
- chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
+ mkdir -p _install/etc/init.d
+ cat <<EOF > _install/etc/init.d/rcS
+ #!/bin/sh
+ mount -t proc none /proc
+ echo Nazdar!!!!
+ EOF
+ chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
Nyní musíte znovu vytvořit RAM-disk a nabootovat.
+3. Zachytávání zpráv jádra spuštěného v emulátoru QEMU do souboru.
+ Zprávy jádra je možné přesměrovat na virtuální sériový port a
+ odtamtud pak například na standardní výstup:
+
+ qemu -serial stdio ...
+
+ a jádru předáme parametr `console=ttyS0`
+
+ qemu -serial stdio -append console=ttyS0 ...
+
+4. Pokud chcete z vašeho systému komunikovat po síti, připojte ho na
+ vnější síť pomocí <abbr title="Network Address
+ Translation">NAT</abbr> na uživatelské úrovni:
+
+ qemu -net nic,vlan=0,model=ne2k_pci -net user,vlan=0 ...
+
+5. Pokud QEMU nebo KVM podporuje vytvoření virtio sítě Plan9 a virtuálního
+ souborového systému, tak je možné propagovat do vnitřního systému
+ obsah adresáře hostitelského systému:
+
+ qemu -virtfs local,path=shared_dir_name,security_model=none,mount_tag=shared_tag ...
+
+ Adresářovou strukturu lze z vnitřního systému připojit následujícími
+ příkazy
+
+ modprobe virtio
+ modprobe virtio_ring
+ modprobe virtio_pci
+ modprobe 9pnet
+ modprobe 9pnet_virtio
+ modprobe 9p
+ mkdir -p /mnt/shareddir
+ mount -t 9p -o trans=virtio shared_tag /mnt/shareddir
+
+Další tipy a triky v oblasti virtualizace používané a odzkoušené zprávci
+sítě na naší katedře nalezente na [Wiki Technické Podpory (support)][support-qemu].
+[support-qemu]:http://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:Virtualiza%C4%8Dn%C3%AD_stroje
+
Jaderné moduly
==============
module_init(hello_init);
module_exit(hello_exit);
-*Příklad převzat z [LDD3][LDD3].*
+*Příklad převzat z [LDD3][LDD3].*
Překlad modulu provedeme pomocí jednoduchého souboru Makefile, který
bude obsahovat jedinou řádku (zde předpokládáme, že výše uvedený
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
-Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
+Tímto říkáme, že příkaz `make` načte `Makefile` z adresáře se
zdrojovými kódy aktuálně běžícího jádra (o který adresář se jedná
-můžete zjistít pomocí `readlink -f /lib/modules/$(uname -r)/build`),
-pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
+můžete zjisti pomocí `readlink -f /lib/modules/$(uname -r)/build`),
+pomocí proměnné `M` řeknete, že se váš modul nachází v aktuálním
adresáři a slovo `modules` na konci znamená, že chcete, aby se
zkompilovaly pouze moduly.
Zadání
======
-Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
-vaše jméno (objeví se ve výstupu příkazu `dmesg`). Jinak nemusí dělat nic.
-Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
-emulátoru.
-
-Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
-objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
-který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
-v [tomto článku][henson_drivers] (strany 2 a 3).
+1. Stáhněte si [[tento program|magic]] ([[32-bitová verze|magic32]]) a
+ zprovozněte ho ve vámi vytvořeném systému. Zprovoznění znamená, že
+ po spuštění program nevypíše žádnou chybu. Nezapomeňte nastavit
+ práva pro spouštění příkazem `chmod +x`.
+
+ Ke zjištění případným problémů by se vám mohly hodit příkazy
+ `strace` a `ltrace`. Ten prvý vypisuje všechna systémová volání
+ vyvolaná daným programem a druhý vypisuje jaké funkce ze sdílených
+ knihoven program volá. Zkuste si například spustit následující
+ příkazy:
+
+ echo Ahoj
+ strace echo Ahoj
+ ltrace echo Ahoj
+
+2. Vytvořte jednoduchý jaderný modul, který po zavedení do jádra vypíše
+ vaše jméno (objeví se ve výstupu příkazu `dmesg`). Jinak nemusí dělat nic.
+ Předveďte činnost vašeho modulu ve vámi vytvořeném systému běžícím v
+ emulátoru.
+
+ Kdo se bude nudit, může zkusit rozšířit modul tak, aby se jeho jméno
+ objevilo v souboru `/proc/myname` nebo vytvořit jednoduchý ovladač,
+ který bude vracet vaše jméno při čtení z `/dev/myname`. Návod najdete
+ v [tomto článku][henson_drivers] (strany 2 a 3).
Tipy a triky
============
-* Pro vyvolání určitého příkazu z historie můžete použít klávesu
+* Pro vyvolání určitého příkazu z historie můžete použít klávesu
`Ctrl-R` následovanou textem hledaného příkazu. Např:
- <Ctrl-R>cpio<Enter>
+ <Ctrl-R>cpio<Enter>
-* Pro rychlé kopírování textu mezi programy (např. příkazy z této stránky do shellu),
+* Pro rychlé kopírování textu mezi programy (např. příkazy z této stránky do shellu),
můžete použít prostřední tlačítko myši. Funguje to tak, že text označíte myší
- (nemačkáte při tom Ctrl-C) a stiskem prostředního tlačítka myši v terminálovém
+ (nemačkáte při tom Ctrl-C) a stiskem prostředního tlačítka myši v terminálovém
okně ho vložíte na příkazovou řádku shellu. Tím, že při tom nemusíte šahat na
klávesnici vám to půjde rychleji.
* Pokud je Qemu spouštěný přes vzdálené připojení (např. server postel),
je potřeba pro zobrazení emulované obrazovky spouštěného stroje
buď provést protunelování X protokolu (`ssh -X`) nebo používat Qemu
- s emulací obrazovky v textovém režimu `qemu -curses`. Další možnost
+ s emulací obrazovky v textovém režimu `qemu -curses`. Další možnost
je emulovat HW bez grafické karty `qemu -nographic` a nastavit testovaný
- systém tak, aby systémová konzole směřovala na sériový port.
+ systém tak, aby systémová konzole směřovala na sériový port
+ (`-append console=ttyS0`).
Reference
=========
* [Linux Device Drivers, Third Edition][LDD3]
* [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
* [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
+* [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)
+* [Filip Navara: Diplomová práce - Rozšíření QEMU o podporu mikrokontroléru AT91SAM7X256](http://rtime.felk.cvut.cz/hw/index.php/AT91SAM7X256)
+* [Aleš Kapica a další: Stránky o virtualizaci z oddělení IT K13135](https://support.dce.felk.cvut.cz/mediawiki/index.php/Kategorie:QEMU)
[LDD3]:http://lwn.net/Kernel/LDD3/
[henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html
+
+<!-- TODO pro pristi rok: Pokud i tohle bude moc jednoduché:
+Zakladni uloha jen za 3 body, za dalsi dva body uloha bez navodu: dame
+jim binarku, ktera bude chctit sdilenou knihovnu a tu budou muset
+napsat. -->