Systemy operacyjne 2009

Transkrypt

Systemy operacyjne 2009
Systemy operacyjne 2009
Pracownia, lista nr 2 dla grupy MSq
Marcin Skórzewski
Web: http://www.ii.uni.wroc.pl/~msq/so09/lab2/: HTML, PDF i TEXMACS
1 grudzień 2009
Spis treści
1. Zadanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2. User-Mode Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.1. Kompilacja jądra UM... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.2. Gdy jestem na pracowni linuksowej... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3. Podpowiedź 1: system plików /proc
.. .. .. .. .. .. ... .. .. .. .. .. .. ... . 3
4. Podpowiedź 2: operacje atomowe w Linuksie
. .. .. ... .. .. .. .. .. .. ... . 3
1. Zadanie
Problem 1. (Na pracowni) Skompiluj i uruchom na pracowni User-Mode Linux w konfiguracji możliwie
na jbliższej do działającej. Przetestuj rozwiązanie problemu 2 pod UML.
Problem 2. (W domu) Napisz moduł będący interfejsem dla problemu „producent–konsument”. Nasz interfejs
ma się komunikować z konsumentami i producentami przez system /proc. Wielkość kolejki produktów ma być
ustalana podczas działania modułu w pliku /proc/proco/max. Producenci to procesy, które produkują liczby
całkowite i przekazują do naszego modułu zapisując do pliku /proc/proco/data. Konsumenci to procesy, które
potrzebują używać liczb generowanych przez producentów i mogą je pobierać odczytując (za każdym razem po
jednej) z pliku /proc/proco/data. Zadanie polega na zapewnieniu synchronizacji. Każda dodana liczba powinna
być tylko raz odebrana.
2. User-Mode Linux
2.1. Kompilacja jądra UM...
Celem jest otrzymanie dwóch podobnych jąder: jednego natywnego do używania, drugiego UserMode o jak najbardziej zbliżonej konfiguracji do testowania. Instrukcja do wykonania na własnym
(domowym) komputerze:
→
mamy dostęp do skompilowanego jądra w katalogu /usr/src/linux/,
→
zakładamy, że jądro ma w konfiguracji włączone opcje:
General setup > Kernel .config support (dostęp do konfiguracji przez /proc/config)
Enable loadable module support (obsługa sterowników czyli modułów)
→
TODO: parametry dla make, żeby mógł kompilować w katalogu, do którego
mamy uprawnienia,
→
oczyszczam źródła jądra:
1
2
Systemy operacyjne 2009
# make ARCH=um mrproper
→
odzyskuje jak najwięcej z dotychczasowej konfiguracji i ustalam parametry specyficzne dla
trybu użytkownika (User-Mode):
# cp /proc/config .config
# make ARCH=um oldconfig
→
warto zaopiekować się parametrami:
Force a static link (STATIC_LINK): Y
Host filesystem (HOSTFS): Y
Management console (MCONSOLE): Y
Virtual block device (BLK_DEV_UBD): Y
stderr console (STDERR_CONSOLE): Y
port channel support (PORT_CHAN): Y
pty channel support (PTY_CHAN): Y
tty channel support (TTY_CHAN): Y
xterm channel support (XTERM_CHAN): Y
→
ostatnie spojrzenie na konfigurację:
# make ARCH=um menuconfig
→
w menu konfiguracyjnym dodaję do opcji „General setup/Local version” prefiks „-um”,
→
wreszcie mogę kompilować:
# make ARCH=um
→
widzę, że jest plik uruchamialny o nazwie „linux” — to jest mój własny User-Mode Linux
→
instaluję sterowniki (moduły) do katalogu „/lib/modules/2.6.26-gentoo-r3-msq1-um/”
(„2.6.*-um” to wersja jądra zwracana przez „uname -r”):
# make ARCH=um modules_install
→
nasz Linuks dla trybu UM powinien być gotowy do uruchomienia, testujemy:
$ ./linux rootfstype=hostfs rw init=/bin/bash
→
wewnątrz UML jestem administratorem, ale proces UML „linux” z punktu widzenia
„zewnętrznego” systemu gospodarza ma niewielkie uprawnienia zwykłego użytkownika,
→
potrzebuję w UML własnego systemy „/proc/”:
# mount -t proc /proc /proc
→
dygresja: jeśli na jakimś systemie komenda „mount” się nie powiedzie, to system macierzysty
nie daje użytkownikowi uprawnień do czytania pliku programu „mount” — żeby uruchomić
program normalnie wystarczy uprawnienie +x, ale UML musi umieć przeczytać plik, który
będzie wewnątrz niego uruchomiony, więc musi być +r,
→
testuję ładowanie sterowników — może być moduł „NTFS”:
# modprobe ntfs
→
wszystko działa, jestem szczęśliwy i gotów do zabawy z modułami
Marcin Skórzewski
3
2.2. Gdy jestem na pracowni linuksowej...
Jak w wariancie wcześniejszym. Różnica polega na braku uprawnień administratora. Jedyną operacją, która wymaga wysokich uprawnień jest instalowanie modułów. Jednym z rozwiązań jest
wirtualna podmiana (podpięcie?) katalogu „/lib/modules/”. Na zewnątrz nie zostanie dokonana
żadna zmiana:
→
wybieram katalog docelowy na moduły:
$ mkdir /tmp/modules
→
uruchamiam UML:
$ ./linux rootfstype=hostfs rw init=/bin/bash
→
przypinam katalog na moduły:
mount -o bind /tmp/modules /lib/modules
→
instaluje moduły (na pozór do „/lib/modules/”, ale na prawdę do „/tmp/modules/”):
# cd /usr/src/linux
# make ARCH=um modules_install
3. Podpowiedź 1: system plików /proc
Właściwie nie podpowiedź, ale przypomnienie. Na stronie z listą tematów są odnośniki do dokumentów gdzie można znaleźć przykłady bardzo prostych modułów komunikujących się przez /proc.
Polecam także „Access the Linux kernel using the /proc filesystem”. Jest tam prosty przykład
odczytywania danych wysłanych z przestrzeni użytkownika przez plik w „/proc”. Listing 9. zawiera
szkielet inicjujący moduł, który obsługuje /proc, natomiast w listingu 10. jest funkcja wywoływana
podczas pisania do pliku.
4. Podpowiedź 2: operacje atomowe w Linuksie
Każdy z was wie dobrze z wykładu co to jest sekcja krytyczna i zna powszechnie używane metody
synchronizacji. W naszym zadaniu potrzebujemy bezpiecznie korzystać ze struktury (lista liczb
produkowanych przez producentów i konsumowanych przez konsumentów) w środowisku wielozadaniowym. Zalecaną w Linuksie metodą są tzw. spin-locki (<asm/spinlock.h>) opisane w pliku
rozdawanym ze źródłami jądra: Documentation/spinlocks.txt (jak i w wielu innych miejscach
w Internecie). Lokalna kopia sformatowana do wygodnego czytania i druku: PDF, TEXMACS . Są
zaprojektowane jako zawsze bezpieczne i mają działać zawsze i wszędzie. Najprostszy przykład
użycia:
static DEFINE_SPINLOCK(xxx_lock);
unsigned long flags;
// początek sekcji krytycznej
spin_lock_irqsave(&xxx_lock, flags);
// kod bezpicznie operujący na strukturze
// zakończ sekcję krytyczną
spin_unlock_irqrestore(&xxx_lock, flags);
O innych metodach można poczytać np. tu: Kernel Locking Techniques (Robert Love) (krótko,
ogólnie i przystępnie) lub tu: Unreliable Guide To Locking (Rusty Russell) (w szczegółach).