SO2 wyklad 1


Systemy Operacyjne  semestr drugi
Wykład pierwszy
 Rodowód Linuksa
Inspiracją dla autora systemu Linux był system Minix napisany przez Andrew Tanenbauma, który bazował z kolei na
systemie Unix. Termin Unix w obecnych czasach oznacza całą rodzinę systemów operacyjnych opartych na wspólnej
filozofii, której zródłem jest projekt systemu operacyjnego, jaki powstał w roku 1969 w Bell Labs, będących częścią
amerykańskiego koncernu AT&T. System ten jest pochodną innego systemu operacyjnego Multics, nad którego
powstaniem pracowano w trzech ośrodkach: w MIT, w AT&T i w General Electric. Firma AT&T po pewnym czasie
wycofała się z prac, ale osoby zatrudnione przy tym projekcie pozostały jej pracownikami. Do ich grona należeli między
innymi Ken Thompson, Dennis Ritchie i Douglas McIlroy. To ta trójka odegrała największą rolę w powstaniu pierwszej
wersji systemu Unix. Pracę nad nią rozpoczęli Ken Thompson i Dennis Ritchie, pisząc cały kod w assemblerze
komputera PDP-7, który poznali tworząc wcześniej grę  Space Travel dla tej platformy sprzętowej. Znaczący wkład do
projektu systemu wniósł Douglas McIlroy, opracowywując np.: łącza nienazwane, które są jednym z środków
zapewniających komunikację między procesami, a także wyznaczając reguły tworzenia kodu, które dziś są częścią
inżynierii oprogramowania. W roku 1973 kod zródłowy Uniksa został w większości przepisany w języku C, który
opracował Dennis Ritchie1, dzięki czemu system ten stał się łatwy w przenoszeniu na inne platformy sprzętowe2. Firma
AT&T podjęła decyzję o rozpoczęciu sprzedaży systemu Unix. Każda jego wersja była rozprowadzana razem z kodem
zródłowym, a więc wiele firm i innych instytucji, które nabyło ten system, mogło go modyfikować wprowadzając nowe
funkcje. Pod względem wprowadzonych do tego systemu innowacji wyróżniał się Uniwersytet Berkeley. Wszystkie
wersje systemu Unix, które powstały w tej placówce były oznaczane nazwą BSD (Berkeley System Distribution).
Największy wkład do prac nad Uniksem BSD wniósł Bill Joy. To w Berkeley powstał słynny edytor vi, powłoka csh,
a także tu dodano do jądra podsystemy odpowiedzialne za obsługę protokołu TCP/IP i pamięć wirtualną. Z czasem te
funkcje zostały włączone do dystrybucji rozpowszechnianej przez AT&T (wersja System III). W chwili obecnej rozwój
gałęzi BSD jest kontynuowany przez takie projekty, jak FreeBSD, OpenBSD, NetBSD i DragonFly BSD. Aby
uporządkować rozwój Uniksa opracowano kilka standardów, z których najważniejszymi są POSIX oraz SUS. Większość
odmian Uniksa spełnia wymagania tych standardów.
W chwili obecnej niemalże wszystkie odmiany Uniksa to systemy wielodostępne i wielozadaniowe, obsługujące
wszystkie rozwiązania w nowoczesnych platformach sprzętowych. Jest jednakże kilka cech, które odróżniają go od
innych systemów operacyjnych. Przede wszystkim jest on systemem o stosunkowo prostej budowie (jego twórcy
stosowali zasadę Keep It Small and Simple  KISS3). Jądro Uniksa implementuje niewielką liczbę wywołań
systemowych, podczas gdy w innych systemach ta liczba dochodzi do dziesiątek tysięcy. Wywołania systemowe
w Uniksie zostały opracowane w myśl zasady sformułowanej przez Douglasa McIlroy'a:  Rób jedną rzecz, ale rób ją
dobrze , co oznacza, że wykonują jedną czynność, ale w sposób uniwersalny. Większość elementów w systemie Unix
jest traktowana jako plik, co znacznie ułatwia zarządzanie urządzeniami i danymi. W końcu Unix ma mechanizmy,
które pozwalają na tworzenie w krótkim czasie nowych procesów, oraz dostarcza środków prostej komunikacji między
nimi4. Unix był także jednym z pierwszych systemów operacyjnych, które zostały napisane w języku wysokiego
poziomu, co uczyniło go systemem przenośnym.
Charakterystyka Linuksa
Linux5 jest systemem uniksopodobnym (ang. Unix-like), ale nie jest Uniksem. Pracę nad jądrem tego systemu
rozpoczął Linus Benedict Torvalds w roku 1991, wzorując się na wspomnianym systemie Minix. Nie oznacza to jednak,
że kod przez niego napisany zawiera fragmenty kodu Miniksa lub oryginalnego Uniksa. Linux powstał  od zera , ale
jest zgodny ze standardami POSIX i SUS. Pierwsza wersja kodu zródłowego Linuksa miała ponad 10 tysięcy wierszy
kodu. Bieżące wersje liczą około 14 milionów linii kodu i są tworzone przez obszerną grupę programistów,
współpracujących ze sobą przez Internet. Prace tej grupy koordynuje oczywiście Linus Torvalds. Kod zródłowy Linuksa
dostępny jest na zasadach licencji GNU GPL v2.0, która gwarantuje, że jest on wolnodostępny. Należy zauważyć, że
słowo Linux ma dwa znaczenia. W powyższym tekście oznaczało ono po prostu jądro systemu operacyjnego. W drugim
znaczeniu, oznacza podstawową wersję systemu operacyjnego, która oprócz jądra zawiera również zestaw narzędzi do
kompilacji programów w językach C i assembler, bibliotekę języka C i powłokę systemową. Wszystkie wymienione tu
elementy, oprócz jądra, zostały stworzone przez fundację GNU, założoną przez Richarda Stallmana. Istnieje wiele
odmian systemu Linux, nazywanych dystrybucjami, które oprócz wymienionych tu podstawowych narzędzi zawierają
również inne oprogramowanie np. system X Window, będący implementacją środowiska graficznego użytkownika, oraz
1 Pozostałą część pozostawiono w assemblerze.
2 Dokładniej  łatwiej było go przenieść na inne platformy, niż system napisany w całości w assemblerze.
3 Właściwie ten skrót rozwijano jako "Keep It Simple, Stupid!". Osobiście wolę wersję łagodniejszą :-)
4 Ostatnio pojawiają się głosy, że te mechanizmy komunikacji stają się powoli przestarzałe.
5 W kwestii językowej: piszemy Linux, ale odmieniamy: Linuksa, Linuksowi, itd.
1
Systemy Operacyjne  semestr drugi
szereg innych aplikacji, niezbędnych użytkownikom. W dalszej części wykładu słowo  Linux będzie oznaczało
wyłącznie jądro systemu operacyjnego. Pierwotnie Linux przeznaczony był tylko na platformę sprzętową i386 (powstał
na komputerze wyposażonym w procesor Intel 80386). Obecnie obsługuje obsługuje całą gamę mniej lub bardziej
popularnych platform sprzętowych, takich jak : AMD64, PowerPC, Ultra Sparc, MIPS. Wspiera również architektury
równoległe (SMP, NUMA).
Zasada działania jądra
Jądro (ang. kernel) systemu (nazywane czasami rdzeniem (ang. core)) jest częścią systemu operacyjnego, która stale
rezyduje w pamięci komputera, nadzoruje pracę sprzętu i aplikacji użytkownika, oraz dostarcza tym ostatnim
określonych usługi. Najczęściej jądro (monolityczne) zawiera takie elementy, jak: procedury obsługi przerwań,
mechanizm szeregowania procesów, mechanizm zarządzania pamięcią i obsługi plików. Jądro pracuje w trybie
uprzywilejowanym, co oznacza, że ma nieograniczony dostęp do wszystkich zasobów systemu komputerowego, w tym
do pamięci operacyjnej. Obszar pamięci (w sensie zakresu adresów) zajmowany przez jądro nazywany jest przestrzenią
adresową jądra. Dosyć często o czynnościach wykonywanych przez jądro mówimy, że zachodzą w przestrzeni jądra.
Procesy użytkownika pracują w trybie procesora, w którym dostęp do zasobów systemu jest ograniczony. Obszary
pamięci (również w sensie zakresu adresów) przyporządkowane aplikacjom użytkownika nazywamy przestrzenią
adresową użytkownika. Analogicznie jak ma to miejsce w przypadku jądra, o czynnościach, które są wykonywane
przez aplikacje mówimy, że są wykonywane w przestrzeni użytkownika. Do komunikacji między procesami
użytkownika, a jądrem służą wywołania systemowe. Zazwyczaj aplikacje użytkownika nie wywołują ich bezpośrednio,
lecz korzystają z funkcji dostępnych w standardowej bibliotece języka C (libc). Niektóre z tych funkcji zawierają sam
kod wywołania funkcji systemowej, czyli są swego rodzaju  opakowaniami na wywołania systemowe, inne funkcje
wykonują przed zainicjalizowaniem wywołania systemowego dodatkowe czynności, jeszcze inne mogą korzystać
z większej liczby wywołań systemowych. Są również funkcje, które nie korzystają w ogóle z wywołań systemowych.
Jeśli jądro wykonuje za pośrednictwem wywołania systemowego jakąś usługę dla aplikacji użytkownika, to działa
w kontekście procesu, co oznacza, że kod jądra realizujący to wywołanie ma dostęp do informacji o procesie, który
korzysta z tego wywołania. W takiej sytuacji można również powiedzieć, że aplikacja wykonuje wywołanie systemowe
w przestrzeni jądra, choć nie jest to określenie poprawne. Jądro systemu jest oprogramowaniem sterowanym
zdarzeniami. Zdarzenia pochodzące od sprzętu są sygnalizowane za pomocą przerwań. Te przerwania pojawiają się
zazwyczaj asynchronicznie6. Z każdym z nich jest związany pewien numer, na podstawie którego jądro odnajduje
i wykonuje odpowiednią procedurę obsługi tego przerwania. Te procedury są wykonywane w kontekście przerwania, co
oznacza, że nie są związane z żadnym konkretnym procesem. Pozwala to przyspieszyć ich działanie. Jądro ma również
możliwość blokowania wszystkich przerwań lub tylko wybranych przerwań, na czas obsługi jednego z nich.
Reasumując, procesor w systemie komputerowym, który kontroluje Linux, albo wykonuje kod aplikacji, albo kod jądra
w kontekście procesu, albo kod jądra w kontekście przerwania.
Porównanie z innymi systemami uniksowymi
Jądro sytemu Linux jest podobne do rdzeni innych systemów wzorowanych na Uniksie, ale istnieje również kilka
znaczących różnic. Podobnie jak w większości Uniksów, jądro Linuksa jest monolityczne, ale udostępnia możliwość
korzystania z ładowanych dynamicznie modułów, które zazwyczaj są sterownikami urządzeń. Linux obsługuje również
symetryczne przetwarzanie wieloprocesorowe (SMP) oraz architekturę NUMA, co nie jest cechą wszystkich Uniksów.
Podobnie jak Solaris i IRIX, Linux może obsługiwać od wersji 2.6 wywłaszczanie zadań jądra. Jądro Linuksa nie
rozróżnia wątków i procesów, traktuje je niemalże w ten sam sposób. Niektóre mechanizmy, które przez twórców
Uniksa zostały uznane za mało wydajne lub wręcz za zbędne (jak np. obsługa strumieni) nie zostały w ogóle
zaimplementowane w jądrze Linuksa. Ze względów wydajnościowych strony pamięci zajmowanej przez jądra Linuksa
nie podlegają wymianie. Ta ostatnia cecha jest konsekwencją faktu, że Linux jest tworzony przez ogromną społeczność
programistów  w wyniku dyskusji i rozważań członkowie tej społeczność doszli do wniosku, że taki mechanizm
spowodowałby pogorszenie wydajności systemu. Kolejne wersje jądra są oznaczane symbolami składającymi się
z trzech7 liczb rozdzielonych kropkami. Pierwsza liczba to główny numer wersji, druga to numer podwersji, trzecia
oznacza kolejne wydanie, w którym dokonano znaczących zmian lub rozbudowano funkcjonalność jądra. Przed
wydaniem jądra 2.6.0 nieparzysty numer podwersji oznaczał wersję rozwojową, która mogła być niestabilna, a numer
parzysty podwersji, wersję stabilną. Od wersji 3.0 jądra numer podwersji oznacza kolejne wydanie, a trzecia liczba
używana jest do oznaczania wersji, w których usunięto wykryte usterki. Wersje rozwojowe oznaczane są za pomocą
liter rc, za którymi występuje numer wersji rozwojowej. Niektóre dystrybucje Linuksa mogą dodawać do tych oznaczeń
dodatkowe liczby.
6 Istnieją również przerwania synchroniczne.
7 Pojawiła się również czwarta liczba (jądro 2.6.8.1). Jej wprowadzenie związane było z naprawieniem poważnego błędu,
który wykryto tuż po wypuszczeniu wersji 2.6.8. Tę numerację stosowano czasem w pózniejszych wersjach.
2
Systemy Operacyjne  semestr drugi
Krótka charakterystyka metodologii programowania jądra
Ponieważ jądro systemu z definicji ma być optymalne pod względem wykorzystania pamięci i szybkości działania, to
przeglądając kod zródłowy Linuksa możemy spotkać wiele fragmentów, które łamią niektóre przyjęte kanony dobrze
napisanego oprogramowania (jak choćby nieużywanie instrukcji goto). Tak, jak w przypadku innych systemów
uniksopodobnych, większość kodu Linuksa jest napisana w języku C, a tylko niewielka część, zależna od konkretnej
architektury sprzętowej w assemblerze8. Pisząc własny fragment jądra, czy to w postaci modułu, czy ingerując
w istniejący kod należy mieć świadomość pewnych ograniczeń. Przede wszystkim, pisząc kod jądra nie mamy dostępu
do funkcji standardowej biblioteki C (libc, a konkretniej glibc). Jest to naturalną konsekwencją tego, że to jądro
stanowi wsparcie dla tej biblioteki, a nie odwrotnie. Na szczęście zostały zaimplementowane w jądrze funkcje, będące
substytutami tych z biblioteki glibc. Zamiast funkcji printf jest funkcja printk, zamiast funkcji do manipulowania
łańcuchami znaków, które są dostępne po włączeniu pliku string.h są podobne funkcje dostępne po włączeniu pliku
linux/string.h. Uogólniając  jądro może korzystać wyłącznie ze swoich plików nagłówkowych, niedozwolone jest
korzystanie z zewnętrznych plików nagłówkowych. Kod jądra jest pisany z wykorzystaniem standardu ISO C99 języka
C, oraz z wykorzystaniem rozszerzeń GNU C. Oznacza to, że może być kompilowany prawie wyłącznie przez kompilator
C pochodzący z GCC (Gnu Compilers Collection). Do wspomnianych rozszerzeń należy wykorzystywanie funkcji
rozwijanych w miejscu wywołania (ang. inline functions), obecnie wprowadzone już do standardu języka C. Takie
funkcje są bardziej bezpieczne i eleganckie niż makra, a przy tym równie skuteczne. Funkcje rozwijane w miejscu
wywołania są definiowane z użyciem słów kluczowych static i inline. Należy jednak pamiętać, aby nie nadużywać
takich funkcji, bo prowadzi to do niepotrzebnego zwiększenia objętości kodu wynikowego. Innym z wykorzystywanych
rozszerzeń jest możliwość wprowadzania specjalnych wstawek assemblerowych do kodu napisanego w języku C. Te
wstawki są stosowane wszędzie tam, gdzie wymagana jest optymalizacja szybkości działania jądra. Kompilator gcc
udostępnia dwie dyrektywy wspomagające optymalizację kodu. Są to likely() i unlikely(). Służą one do oznaczania
prawdopodobieństwa wykonania kodu w instrukcjach warunkowych, np.: jako unlikely() możemy zaznaczyć warunki
związane z obsługą większości wyjątków. Pisząc kod działający w przestrzeni jądra musimy pamiętać, że nie mamy
 siatki zabezpieczającej w postaci ochrony pamięci. Jeśli będziemy zle zarządzać pamięcią jądra, to możemy naruszyć
stabilność systemu operacyjnego. Jeśli chcemy użyć liczb i arytmetyki zmiennoprzecinkowej, to musimy sami
oprogramować FPU, jednakże nigdy dotąd potrzeba używania takiej arytmetyki w przestrzeni jądra nie zaistniała.
Rozmiar stosu jądra9 jest ograniczony i wynosi w przypadku architektur 32 bitowych 8 KiB10, a w przypadku 64
bitowych procesorów Alpha 16 KiB. Procesy użytkownika dysponują stosem znajdującym się w przestrzeni
użytkownika, który nie jest ograniczony11. Programując w jądrze musimy pamiętać o synchronizacji dostępu do
zasobów współdzielonych. Mamy do dyspozycji np. takie środki synchronizacji jak semafory i rygle pętlowe (ang. spin-
lock), czyli semafory z aktywnym oczekiwaniem. Ostatnią ważną rzeczą, o której należy pamiętać pisząc lub zmieniając
kod jądra, to przenośność. Nawet pisząc kod w języku C możemy doświadczyć różnych problemów, jak choćby
porządek bitów i bajtów w słowie, czy rozmiary poszczególnych typów danych.
Bardzo krótkie wprowadzenie do tworzenia modułów jądra 2.6 i nowszych12
Moduły jądra są formą bibliotek współdzielonych, jednakże nie są one dynamicznie łączone z procesami użytkownika
lecz z samym jądrem. Dzięki modułom możemy łatwo dodawać lub usuwać nowe funkcje do jądra, bez konieczności
restartowania systemu. Pisząc własny moduł należy być świadomym tego, że błąd w module może spowodować
poważne konsekwencje dla pracy systemu, a w niektórych przypadkach może również doprowadzić do uszkodzenia
sprzętu.
Sposób pisania modułów dla jądra Linuksa 2.6 i nowszych różni się od tego, który obowiązywał we wcześniejszych
wersjach. Przede wszystkim, aby skompilować moduł należy mieć zainstalowany, w zależności od wersji jądra, cały
jego kod zródłowy lub specjalną wersję do kompilacji modułów. Kompilację wykonujemy za pomocą programu
narzędziowego  make . W ramce poniżej przedstawiona została zawartość przykładowego pliku konfiguracyjnego
(Makefile) dla tego programu.
Treść tego pliku została zapożyczona z dokumentu pt. "The Linux Kernel Module Programming Guide", którego
autorami są Peter Jay Salzman, Michael Burian i Ori Pomerantz, a który jest dostępny pod adresem
http://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf. Plik ten zawiera regułę  clean , która usuwa pliki powstałe w wyniku
8 Dodajmy: w notacji AT&T.
9 Określenia co najmniej mylące. Chodzi o stos jądra, który jest przydzielany każdemu procesowi użytkownika
i używany jeśli ten proces zainicjalizuje wywołanie systemowe.
10 Istnieje możliwość zmniejszenia tego rozmiaru do 4 KiB.
11 Dokładniej: większość dystrybucji Linuksa ograniczają rozmiar stosu do 8MiB, ale użytkownik uprzywilejowany może
znieść te ograniczenia.
12 Całość rozdziału (wraz z przykładami) bazuje na książce Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman,
"Linux Device Drivers".
3
Systemy Operacyjne  semestr drugi
kompilacji pliku z kodem zródłowym modułu.
Aby program  make wykonał regułę  clean
obj-m := first.o
należy go wywołać następująco:  make clean .
KERNELDIR = /lib/modules/$(shell uname -r)/build
Wywołania programu bez parametru spowoduje
default:
skompilowanie modułu o nazwie  first . Który
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules moduł ma zostać skompilowany określa wiersz
 obj-m := first.o pliku konfiguracyjnego.
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
Moduł o nazwie  first jest modułem typu  Hello World! , który powinni stworzyć wszyscy początkujący programiści,
chcący pisać własne moduły (kod należy umieścić w pliku o nazwie  first.c ):
#include
static int __init first_init(void)
{
printk(KERN_ALERT"Welcome\n");
return 0;
}
static void __exit first_exit(void)
{
printk(KERN_ALERT"Good bye\n");
}
module_init(first_init);
module_exit(first_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arkadiusz Chrobot ");
MODULE_DESCRIPTION("Another \"Hello World!\" kernel module :-)");
MODULE_VERSION("1.0");
Plik nagłówkowy  linux/module.h jest dołączny do kodu każdego modułu jądra. Zawiera on między innymi makra
preprocesora, które zostaną opisane niżej. Funkcje o nazwach  first_init i  first_exit są odpowiedzialne odpowiednio
za wykonanie inicjalizacji tuż po załadowaniu modułu i deinicjalizację tuż przed usunięciem modułu z pamięci
operacyjnej. Obie funkcje zostały zdefiniowane z użyciem słowa kluczowego static, co oznacza, że są dostępne
wewnątrz przestrzeni nazw modułu  first , co zapobiega ewentualnemu konfliktowi nazw. Żadna z tych funkcji nie
przyjmuje parametrów wywołania. Funkcja  first_exit nic również nie zwraca, natomiast  first_init zwraca wartość
typu int. Jeśli użylibyśmy terminologii znanej z języków obiektowych, to o tych funkcjach możemy myśleć jako
o konstruktorze i destruktorze. W nagłówkach takich funkcji mogą, ale nie muszą występować znaczniki __init i __exit.
Pierwszy sygnalizuje, że funkcja jest używana wyłącznie podczas inicjalizacji modułu i po jej wykonaniu można zwolnić
pamięć na nią przydzieloną. Drugi znacznik sygnalizuje, że funkcja jest używana wyłącznie podczas sprzątania. Ten
znacznik ma znaczenie jeśli moduł jest włączany do kodu jądra na etapie kompilacji, lub gdy jądro jest tak
skonfigurowane, że nie pozwala na usunięcie załadowanych modułów. Makra module_init oraz module_exit przyjmują
jako parametry wywołania adresy funkcji odpowiedzialnych za inicjalizację i sprzątanie po module. Te makra
pozwalają programiście powiadomić kompilator, które funkcje będą odpowiedzialne za inicjalizację i sprzątanie po
module. Cztery pozostałe makra nie są obowiązkowe i pozwalają określić licencję na jakiej moduł jest
rozpowszechniany, autora modułu (zalecane jest podanie jego adresu e-mail), opis modułu oraz jego wersję. Wszystkie
te informacje są zapisane w postaci łańcuchów znaków, według konwencji obowiązującej w języku C. Mając plik
wynikowy możemy je odczytać posługując się programem  modinfo np.:  modinfo first.ko . Nieumieszczenie w kodzie
modułu makra MODULE_LICENSE lub podanie nazwy innej niż ta, która określa jedną z wolnych licencji spowoduje
wystąpienie komunikatu ostrzegawczego, mówiącego o tym, że jądro zostało  skażone modułem o nieznanej lub
niedopuszczalnej licencji. Nazwy licencji, które nie generują takiego ostrzeżenia, to:  GPL ,  GPL v2 ,  GPL additional
rights ,  Dual BSD/GPL ,  Dual MPL/GPL . Moduły na licencji niewolnej mogą jako parametr tego makra przekazać
 Proprietary . W kodzie modułu występują wywołania funkcji  printk . Warto zwrócić uwagę na znacznik będący
argumentem wywołania tej funkcji i poprzedzający właściwy łańcuch znaków. Określa on poziom ważności
4
Systemy Operacyjne  semestr drugi
emitowanego komunikatu lub inaczej poziom logowania. Istnieje kilka takich znaczników: KERN_EMERG  sytuacja
awaryjna, KERN_ALERT  problem wymagający natychmiastowej reakcji, KERN_CRIT  sytuacja krytyczna,
KERN_ERR  błąd, KERN_WARNING  ostrzeżenie, KERN_NOTICE  sytuacja normalna, ale zaszło zdarzenie godne
odnotowania, KERN_INFO  informacja, KERN_DEBUG  komunikat diagnostyczny. Komunikaty od modułów jądra
zapisywane są w buforze komunikatów jądra, a stąd mogą być skopiowane do pliku dziennika systemowego (zazwyczaj
/var/log/messages), wypisywane na konsolę i można je wyświetlić na ekran za pomocą polecenia  dmesg . Moduły
jądra możemy ładować lub usuwać będąc zalogowanymi jako użytkownik  root lub jako użytkownik posiadający takie
uprawnienia (patrz polecenia  sudo i  su ). Korzystając z polecenia  insmod możemy załadować moduł, a poleceniem
 rmmod usunąć, np.:  insmod first.ko ,  rmmod first . Informacje o załadowanych modułach możemy uzyskać
używając polecenia  lsmod , nawet będąc zalogowanymi jako zwykły użytkownik. Istnieją również inne narzędzia do
obsługi modułów, które nie będą tutaj opisywane (np.  modprobe ). Ze względu na dosyć częste zmiany w API jądra
warto zapoznać się z działaniem makrodefinicji preprocesora LINUX_VERSION_CODE i KERNEL_VERSION. Pierwsza
zwraca wersję zródeł jądra zainstalowanych w systemie w postaci wartości typu int, a druga zamienia numer wersji
jądra przekazany jej przez argumenty w postaci trzech liczb (np. KERNEL_VERSION(2,6,19)) na postać numeryczną.
Dzięki nim możemy napisać odpowiednie instrukcje warunkowe dla preprocesora, aby włączał fragmenty kodu
przeznaczone dla danej wersji jądra podczas kompilacji.
5


Wyszukiwarka

Podobne podstrony:
SO2 wyklad 9
SO2 wyklad
SO2 wyklad Warstwa operacji blokowych
SO2 wyklad Przestrzeń adresowa procesów
SO2 wyklad
SO2 wyklad 4 Wywołania systemowe
SO2 wyklad 8
SO2 wyklad Obsługa sieci
SO2 wyklad
SO2 wyklad 7
SO2 wyklad 3
SO2 wyklad
SO2 wyklad 5
SO2 wyklad 2
SO2 wyklad 6
SO2 wyklad 2 Zarządzanie procesami
SO2 wyklad
SO2 wyklad 4

więcej podobnych podstron