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).