Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
28
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
29
www.lpmagazine.org
lin
ux
@
so
ftw
ar
e.
co
m
.p
l
Linux Kernel: Podróż
do wnętrza systemu
Część pierwsza (1/7): Wprowadzenie, kompilacja i instalacja
Wszyscy wiemy, że jądro jest podstawową częścią systemu operacyjnego, odpowiedzialną za tak
newralgiczne zadania jak zarządzanie zasobami sprzętowymi oraz izolację procesów. Wszystkie
najpopularniejsze dystrybucje systemu Linux dostarczane są w postaci gotowej całości – programów
skompilowanych i skonfigurowanych tak, aby działały bezproblemowo na możliwie jak największej
liczbie komputerów. To właśnie uniwersalność i łatwość konfiguracji przyczyniły się do eksplozji
zainteresowania systemami linuksowymi w ostatnich latach. Czy jednak naprawdę musimy decydować
się na gotowe, ale w dużym stopniu nieoptymalne dla naszych potrzeb rozwiązania?
Rafał Kułaga
D
awno, dawno temu, kiedy nie było jesz-
cze dystrybucji systemu Linux w formie,
do jakiej przywykliśmy obecnie, cały sys-
tem należało budować od podstaw. Powo-
dowało to bardzo wiele problemów, głównie ze względu
na ogromną wiedzę, jaką należało posiąść przed rozpoczę-
ciem budowy systemu dla określonego komputera. Wyni-
ki były jednak świetne – systemy tworzone według takiej
filozofii były doskonale dopasowane do danego kompute-
ra, nie tylko poprzez odpowiedni wybór oprogramowania,
lecz również sztuczki stosowane na etapie kompilacji. Ta-
kie podejście do dziś ma wielu zwolenników, szczególnie
wśród starszych użytkowników systemów opartych na ją-
drze Linux, ogranicza jednak dostępność systemu dla po-
czątkujących.
W celu rozwiązania wymienionych problemów, po-
wstały dystrybucje systemu Linux. Ich wykorzystanie za-
wsze jest kompromisem pomiędzy wydajnością, a wygo-
dą obsługi. Pomimo faktu, iż niektóre dystrybucje pozwa-
lają na budowę pakietów ze źródeł w trakcie instalacji (np.
Gentoo), większość korzysta z tzw. pakietów binarnych
– zawierających oprogramowanie w formie gotowej do
uruchomienia. Takie rozwiązanie ogranicza oczywiście
liczbę architektur sprzętowych, na których może zostać
uruchomiona dana wersja dystrybucji, pozwala jednak
na dotarcie do szerokiej grupy odbiorców. Dla przeciętne-
go użytkownika, przyzwyczajonego do systemów z rodzi-
ny Microsoft Windows, przesiadka na dowolną dystrybu-
cję byłaby z pewnością nieznośna, gdyby nie dostępność
oprogramowania w postaci binarnej.
Dlaczego wspominam o tych zagadnieniach we wstę-
pie pilotażowego artykułu cyklu o budowie, konfiguracji i
programowaniu jądra Linux? Otóż dlatego, iż odpowied-
nia konfiguracja jądra systemu może przyczynić się do
znacznego wzrostu wydajności oraz bezpieczeństwa sys-
temu. Jeżeli nie dokonałeś rekompilacji jądra systemu, to
z bardzo dużym prawdopodobieństwem jest ono nieopty-
malne dla Twoich potrzeb.
Jądro rezyduje w pamięci przez cały czas, gdy uru-
chomiony jest system operacyjny. To ono decyduje o tym,
przez jak długi okres czasu (zwany kwantem czasu) pro-
ces wykonywany jest przez procesor. Jeżeli jądro napisa-
ne byłoby w sposób nieoptymalny, to w znacznym stopniu
odbiłoby się to na wydajności całego systemu.
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
28
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
29
www.lpmagazine.org
Aby w pełni zrozumieć zasadę działania
jądra systemu oraz poszczególnych jego me-
chanizmów, konieczne jest zapoznanie się z
podstawowymi paradygmatami związanymi
z budową tej części systemu. W tym cyklu ar-
tykułów zostaną poruszone zagadnienia takie
jak: rekompilacja jądra, proces uruchamiania
systemu, zarządzanie procesami oraz zasoba-
mi, obsługa systemów plików, mechanizmy
sieciowe systemu Linux, mechanizmy zabez-
pieczeń na poziomie jądra (SELinux), tworze-
nie modułów jądra oraz pisanie prostych ste-
rowników urządzeń.
Nie szkodzi, jeżeli wcześniej nie miałeś
styczności z tymi zagadnieniami – wszyst-
ko zostanie przejrzyście omówione na przy-
kładach. Aby jednak w pełni skorzystać z in-
formacji zawartych w tym cyklu, powinie-
neś opanować język C przynajmniej w stop-
niu podstawowym – jest to bowiem język
programowania w którym zostało napisa-
ne jądro.
W tej części cyklu zajmiemy się pod-
stawami budowy jądra systemu operacyjne-
go. Podstawowym tematem tego artykułu jest
jednak wybór odpowiedniej wersji jądra Li-
nux, jego kompilacja oraz wykorzystanie w
systemie. Zapraszam do lektury!
Jądro systemu
Zanim przejdziemy do dalszej części artykułu,
w której zajmiemy się praktycznymi aspekta-
mi konfiguracji jądra Linux, warto zastanowić
się nad budową tej części systemu oraz jego
miejscem w architekturze nowoczesnego sys-
temu operacyjnego.
Zadania jądra
We współczesnym modelu warstwowej bu-
dowy systemu komputerowego, jądro syste-
mu odpowiada za zapewnienie środowiska
dla aplikacji uruchamianych przez użytkow-
nika. We współczesnych systemach ope-
racyjnych działa jednocześnie wiele róż-
nych aplikacji, a jak wiemy, procesor mo-
że jednocześnie wykonywać tylko jeden
program (pomijam tu procesory wielordze-
niowe lub systemy wieloprocesorowe). Pro-
blemem jest również zapewnienie izolowa-
nego środowiska działania dla każdego pro-
cesu – niemożliwe jest bowiem wykorzysta-
nie jednej przestrzeni adresowej przez wie-
le programów. Konieczne jest także zdefi-
niowanie mechanizmów obsługi urządzeń
wejścia/wyjścia oraz zapewnienie możli-
wości komunikacji międzyprocesowej, oraz
wywołań systemowych, wykorzystywanych
w celu komunikacji procesów z jądrem (Ry-
sunek 1).
W celu zapewnienia możliwości jedno-
czesnego wykonywania wielu procesów, wy-
korzystywana jest część jądra zwana schedu-
lerem, odpowiadająca za określanie, który
proces ma mieć w danej chwili dostęp do pro-
cesora oraz czasu tego dostępu (zwany kwan-
tem). Po upłynięciu kwantu, lub zaistnieniu
innego zdarzenia powodującego koniecz-
ność przerwania wykonywania danego pro-
cesu, dokonywane jest wywłaszczenie zada-
nia. Wskutek wywłaszczenia, następne zada-
nie (określane przez algorytm kolejkowania)
uzyskuje dostęp do procesora. Jądro systemu
pozwalające na jednoczesne działanie wielu
procesów, nazywamy wielozadaniowym.
Każdy z uruchamianych programów
wymaga do poprawnego działania wła-
snej przestrzeni adresowej. Przy wywoła-
niu programu, jądro alokuje niezbędną pa-
mięć (m. in. stos) oraz wykonuje skok pod
adres określający początek kodu aplikacji.
Każdy z procesów działa w podobny spo-
sób, w jaki byłby wykonywany gdyby był
jedynym zadaniem wykonywanym przez
procesor – wszelkie funkcje związane z za-
pewnieniem ochrony obszarów wykorzysty-
wanych przez inne aplikacje przejmuje ją-
dro systemu. Stosowane w tym celu tech-
niki nazywane są pamięcią wirtualną – po-
zwalają bowiem na nadawanie obszarom pa-
mięci fizycznej dowolnie określonych ad-
resów, które następnie wykorzystywane są
przez procesy. Funkcje te wymagają wspar-
cia ze strony procesora, a konkretnie jego
części zwanej MMU (ang. Memory Mana-
gement Unit).
W trakcie wykonywania programów, bar-
dzo często okazuje się, że ilość pamięci RAM
naszego komputera jest niewystarczająca do
przechowywania wszystkich niezbędnych da-
nych. W takiej sytuacji, nowoczesne jądra sys-
temu zapisują określone fragmenty pamięci
na urządzeniach pamięci masowej, takich jak
dyski twarde. Gdy zaistnieje potrzeba odwoła-
nia się do danych znajdujących się na partycji
wymiany (ang. swap partition), jądro wczytu-
je określony obszar do pamięci operacyjnej.
Technika ta pozwala na wydajniejszą obsługę
dużych aplikacji.
W celu skutecznego wykonywania swo-
ich funkcji, jądro musi zostać odizolowane
od wykonywanych aplikacji. Umożliwia to
zastosowanie podziału na przestrzeń użyt-
kownika (ang. userspace) oraz jądra (ang.
kernelspace). Procesy działające w przestrze-
ni użytkownika nie mają dostępu do danych
znajdujących się w przestrzeni jądra. Wsku-
tek tego, dane jądra nie są narażone na mo-
dyfikację przez niepowołane procesy. Zwróć
uwagę, że taka ingerencja w zawartość pa-
mięci zawierającej kod jądra mogłaby stano-
wić ogromne zagrożenie dla bezpieczeństwa
systemu – pamiętajmy, że to jądro decyduje,
czy dany użytkownik uprawniony jest do do-
stępu do danego pliku, wywołania systemo-
wego itp.
Skoro procesy nie mają dostępu do prze-
strzeni jądra, to w jaki sposób odbywa się ich
komunikacja z jądrem? Pamiętamy przecież,
że każdy z procesów działa w osobnej, wir-
tualnej przestrzeni adresowej. W celu zapew-
nienia możliwości komunikacji międzypro-
cesowej wykorzystywane są rozmaite techni-
ki, takie jak deskryptory plików, sygnały, se-
mafory, gniazda oraz kolejki wiadomości. Ich
działanie polega na wykorzystaniu funkcji za-
pewnianych przez jądro systemu. Wywołanie
większości z nich odbywa się przy użyciu tzw.
wywołań systemowych (ang. system calls, po-
tocznie syscalls).
W obrębie jądra systemu (lub jako tzw.
moduły) funkcjonują sterowniki urządzeń.
Ich działanie opiera się na zapewnieniu war-
stwy abstrakcji dla funkcji realizowanych
w ścisłej zależności od wykorzystywanego
sprzętu. Dzięki temu, programista nie musi
znać szczegółów działania sprzętu, lecz jedy-
Rysunek 1.
Budowa systemu operacyjnego z ją-
drem monolitycznym
���������������������
�����������������
����������������������������
���
������
�����������
���
Rysunek 2.
Budowa systemu operacyjnego korzy-
stającego z mikrojądra
�������
����������
�����������
�
�
�
��������������������������
30
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
31
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
nie zestawy wywołań, służących do obsługi
mechanizmów abstrakcji.
Przestrzeń jądra
a przestrzeń użytkownika
Jak już powiedzieliśmy, w większości syste-
mów operacyjnych istnieje wyraźny podział
na przestrzeń jądra oraz przestrzeń użytkow-
nika. Większość z Czytelników z pewnością
miała do czynienia z tworzeniem aplika-
cji działających w przestrzeni użytkowni-
ka. Cykl ten ze względu na naturę tematyki
będzie zajmował się głównie zagadnienia-
mi związanymi z przestrzenią jądra. Czym
więc, w dużym skrócie, charakteryzuje się
programowanie w przestrzeni jądra?
Będąc w przestrzeni jądra, mamy pełen
dostęp do wszystkich zasobów systemu. Wy-
nikają z tego nie tylko bardzo duże możliwo-
ści, lecz również odpowiedzialność – musi-
my mieć świadomość, że każdy z błędów mo-
że spowodować zawieszenie systemu, lub,
co gorsza, narażenie przechowywanych da-
nych. Z tego względu, w zagadnieniach zwią-
zanych z realizacją funkcji charakterystycz-
nych dla jądra, istnieje tendencja do przeno-
szenia ich do przestrzeni użytkownika, gdzie
mogłyby być realizowane przez wyspecjalizo-
wane serwery.
Następną różnicą, której bardzo często nie
uświadamiają sobie początkujący programiści,
jest to, iż moduły jądra (oraz jego część głów-
na, nazywana statyczną) nie mają dostępu do
funkcji biblioteki standardowej C. W modu-
le jądra nie możemy więc wywołać np. funk-
cji
printf()
, ponieważ kod ten nie jest linko-
wany z biblioteką standardową (cechę tę okre-
śla się jako samodzielność). Większość funk-
cji posiada jednak odpowiedniki, które może-
my wykorzystać w tworzonych przez nas mo-
dułach jądra, np. dla funkcji
printf()
jest nim
kprintf()
.
Oczywiście istnieje jeszcze wiele innych
różnic, które omówimy w następnych czę-
ściach cyklu, a w szczególności w części do-
tyczącej tworzenia modułów jądra.
Rodzaje jądra systemu
Istnieje wiele metodologii budowy jądra sys-
temu operacyjnego. Głównym parametrem,
pod względem którego dokonywany jest po-
dział na poszczególne kategorie, jest rozdzie-
lenie zadań jądra pomiędzy serwery działają-
ce w przestrzeni użytkownika oraz część ją-
dra rezydującą w przestrzeni jądra. Nie moż-
na jednoznacznie orzec, która z tych meto-
dologii jest najlepsza – każda ma swoje za-
lety i wady oraz znajduje zastosowania w in-
nej klasie systemów operacyjnych (np. syste-
mów dla urządzeń wbudowanych).
Najważniejsze z istniejących obecnie filo-
zofii budowy jądra systemu to:
• Jądro monolityczne;
• Mikrojądro;
• Jądro hybrydowe;
• Nanokernel i exokernel.
Przyjrzyjmy się krótko każdemu z tych typów.
Jądro monolityczne
Koncepcja jądra monolitycznego (ang. mo-
nolithic kernel) polega na budowie jądra ja-
Rysunek 3.
Schemat numeracji wersji jądra Linux serii 2.6
������
������
����������
����������
����������
����������
����������
����������
��������
��������
��������
��������
Rysunek 4.
Strona główna kernel.org
30
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
31
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
ko jednolitego, dużego programu działają-
cego w przestrzeni jądra (Rysunek 1). Kla-
syczne jądro monolityczne zajmuje się obsłu-
gą wszystkich funkcji jądra systemu, jednak
większość wykorzystywanych obecnie ją-
der, budowanych w oparciu o tą metodolo-
gię posiada możliwość dynamicznego dołą-
czania modułów, gdy nastąpi taka potrzeba
(np. po podłączeniu do komputera urządze-
nia pamięci masowej USB). Przykładem ją-
dra monolitycznego jest Linux oraz jądra sys-
temów UNIX.
Największą zaletą jądra monolitycznego
jest jego wysoka wydajność, wynikająca z za-
stosowania jednej, spójnej przestrzeni adreso-
wej, w której działa większość mechanizmów
jądra. Dzięki temu, nie jest konieczne przełą-
czanie kontekstów procesów przy wykonywa-
niu podstawowych funkcji systemu, tak jak ma
to miejsce w mikrojądrach, wykorzystujących
dużą liczbę serwerów przestrzeni użytkowni-
ka. Znacznie ułatwiona zostaje również komu-
nikacja pomiędzy poszczególnymi elementa-
mi jądra.
Główna wada jądra monolitycznego wy-
nika z tej samej cechy, która jest źródłem
wszystkich jego zalet, a mianowicie – zasto-
sowania jednorodnej przestrzeni adresowej.
Podejście takie powoduje bowiem znacz-
ną komplikację rozwoju jądra oraz dużą po-
datność na błędy. Co więcej, wspólna prze-
strzeń adresowa oznacza, iż błąd w jednej
części jądra może spowodować awarię całe-
go systemu.
Mikrojądro
Zupełnie inne podejście do realizacji za-
dań jądra systemu reprezentuje koncepcja
mikrojądra. Opiera się ona na implemen-
tacji jedynie podstawowych i zupełnie nie-
zbędnych funkcji w programie działającym
w przestrzeni jądra. Pozostałe funkcje reali-
zowane są przy użyciu tzw. serwerów – pro-
gramów działających w przestrzeni użyt-
kownika (Rysunek 2). Przykładem mikro-
jądra jest jądro systemu BeOS, MINIX oraz
Mach i L4.
Podstawową zaletą mikrojądra jest teo-
retycznie większe bezpieczeństwo, wynika-
jące ze znacznego uproszczenia kodu dzia-
łającego w trybie jądra. Serwery działają w
przestrzeni użytkownika, przez co podlega-
ją podobnym ograniczeniom co większość
procesów. Mikrojądra doskonale nadają się
do zastosowania w systemach wbudowa-
nych, dzięki znacznie mniejszej ilości pa-
mięci zajmowanej przez programy niezbęd-
ne do wykonywania podstawowych funk-
cji systemu.
Jak już wspomnieliśmy w paragrafie do-
tyczącym jąder monolitycznych, główną wa-
dą mikrojądra jest duży wydatek oblicze-
niowy związany z przełączaniem pomiędzy
serwerami działającymi w przestrzeni użyt-
kownika. Co więcej, w rozbudowanych sys-
temach operacyjnych, przeznaczonych dla
komputerów typu desktop, mikrojądro wraz
z serwerami może zajmować znacznie więcej
pamięci niż standardowe jądro monolityczne.
Wynika to z faktu, iż każdy serwer jest osob-
nym programem, który dodatkowo może być
napisany w języku wysokiego poziomu. Pro-
blematyczne jest również zapewnienie ko-
munikacji pomiędzy procesami użytkowni-
ka a serwerami.
Rysunek 5.
Program konfiguracyjny jądra działający w trybie tekstowym
Rysunek 6.
Program konfiguracyjny jądra działający w trybie tekstowym
32
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
33
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
Jądro hybrydowe
Jądra posiadające zarówno cechy mikroją-
dra jak i jądra monolitycznego, nazywamy
hybrydowymi. Podstawowe założenie pozo-
staje w ich przypadku takie samo, jak w mi-
krojądrach – znaczna część funkcji realizo-
wana jest przy pomocy serwerów działają-
cych w przestrzeni użytkownika. Jądra hy-
brydowe charakteryzuje się jednak realizacją
pewnych funkcji w programie działającym w
przestrzeni jądra, w celu zwiększenia wydaj-
ności. Przykładem jądra hybrydowego jest
jądro wykorzystywane w systemach rodziny
Microsoft Windows NT.
Nanokernel i exokernel
Wraz z rozwojem systemów operacyjnych
przeznaczonych dla urządzeń wbudowanych,
coraz większe znaczenie ma minimalizacja
wymagań sprzętowych jakie narzuca jądra.
Odpowiedzią na te potrzeby są dwa nowe typy
jądra systemu: nanokernel oraz exokernel.
Pod pojęciem nanokernela rozumiemy ją-
dro zbudowane w oparciu o założenia charak-
terystyczne dla mikrojądra, ze szczególnym
naciskiem na minimalizację objętości progra-
mu znajdującego się stale w pamięci. Nano-
kernel ma za zadanie realizować jedynie pod-
stawowe funkcje jądra, w sposób jak najbar-
dziej efektywny.
Exokernel jest nanokernelem, w którym
zadania związane z zarządzaniem zasobami
systemu zostały przekazane aplikacjom prze-
strzeni użytkownika. Zadaniem jądra jest je-
dynie zapewnienie, że procesy nie będą nad-
pisywać danych należących do innych pro-
cesów.
Jądro Linux
Po zapoznaniu się z podstawami budowy
systemów operacyjnych, nadszedł czas aby-
śmy skupili się na jądrze Linux. Nie jest to
jedynie zbiór wielu milionów linii kodu,
który na początku lat 90 umożliwił zbudo-
wanie pełnowartościowego, wolnego syste-
mu operacyjnego, ale również największy
na świecie program o otwartym kodzie źró-
dłowym. Zajmiemy się teraz krótko histo-
rią, budową oraz architekturami, na których
działa jądro Linux.
Historia Linuksa
Wszyscy wiemy, iż osobą odpowiedzialną za
rozpoczęcie prac nad jądrem Linux jest Linus
Torvalds. Za datę powstania systemu przyjmu-
je się 26 sierpnia 1991, kiedy to wysłał on na
grupę dyskusyjną wiadomość, informującą o
tworzonym amatorsko systemie operacyjnym.
Linus Torvalds z pewnością nie mógł przewi-
dzieć, że jego dzieło stanie się początkiem re-
wolucji.
Jak wiemy, system operacyjny skła-
da się ze znacznie większej ilości kompo-
nentów niż samo jądro. W celu utworzenia
kompletnego systemu operacyjnego, jądro
Linux połączono z narzędziami przestrzeni
użytkownika, zapewnianymi przez projekt
GNU, zapoczątkowany we wrześniu 1983
roku przez Richarda Stallmana. Zdaniem
części osób ze społeczności związanych z
tymi projektami, prowadzi to do konieczno-
ści określania całości jako GNU/Linux (jest
tak np. w dystrybucji Debian GNU/Linux).
Nie będziemy tu roztrząsać tego tematu, po-
nieważ nie jest on zbyt ważny z punktu wi-
dzenia cyklu artykułów. Obiektywnym fak-
tem pozostaje jednak, iż rozwój Linuksa nie
byłby możliwy bez narzędzi dostarczanych
przez projekt GNU.
Już w 1993 roku powstały pierwsze dys-
trybucje systemu Linux, pozwalające na je-
go wykorzystanie przez zwykłego użytkow-
nika – Slackware i Debian. Znamienne jest, iż
nazwa dystrybucji Slackware, obecnie uzna-
wanej za przeznaczoną dla zaawansowanych
użytkowników, oznacza w wolnym tłuma-
czeniu oprogramowanie dla leniwych. W po-
czątkach systemu Linux, za leniwych uznawa-
no bowiem tych, którzy nie budowali systemu
od podstaw.
W ostatnich latach znacznie wzrosło za-
interesowanie Linuksem wśród początkują-
cych użytkowników komputerów. Stało się
to głównie za sprawą dystrybucji takich jak
Ubuntu, które główny nacisk kładą na ła-
twość instalacji i konfiguracji. Z pewnością
jest to zjawisko bardzo korzystne dla całej
społeczności – producenci sprzętu kompute-
rowego zaczynają bowiem postrzegać Linuk-
sa na równi z systemami Microsoft Windows.
Oznacza to nie tylko zwiększoną dostępność
sterowników, lecz również znacznie lepszą
kompatybilność urządzeń z systemami spod
znaku pingwina.
Budowa jądra Linux
Jądro Linux jest typowym jądrem monolitycz-
nym. Obsługuje jednak możliwość dynamicz-
nego dołączania fragmentów kodu, w postaci
tzw. modułów.
Obecnie, jądro Linuksa składa się z pra-
wie 12 milionów linii kodu. Jest to jeden z naj-
większych i najszybciej rozwijanych progra-
mów na świecie.
Nie chcę jednak wyprzedzać treścią na-
stępnych artykułów – budową wszystkich
najważniejszych mechanizmów jądra oraz
tworzeniem modułów i prostych sterow-
ników zajmiemy się w dalszych częściach
cyklu.
Obsługiwane architektury
Systemom opartym na jądrze Linux często
zarzuca się niedopasowanie do potrzeb ty-
powego użytkownika komputera. Z opinią
tą można się zgadzać lub nie, trzeba jednak
przyznać, iż jest to niezwykle elastyczny
system, który znajduje bardzo wiele zasto-
sowań, począwszy od zabawek i systemów
wbudowanych, aż do najszybszych super-
komputerów na świecie.
Niektóre z architektur wspieranych przez
jądro Linux to: x86 (większość kompute-
rów osobistych), 64-bitowe rozwiązania Inte-
la i AMD, mikrokontrolery oparte na rdzeniu
ARM (wykorzystywanego w ogromnej ilości
systemów wbudowanych), procesory oparte
na rdzeniu MIPS (sieciowe systemy wbudo-
wane), PowerPC (wydajne procesory RISC,
przeznaczone m.in. dla systemów wbudowa-
nych), Microblaze (architektura, którą może-
my implementować w układach logiki progra-
mowalnej FPGA).
Na rynku urządzeń mobilnych widać ten-
dencję do stosowania systemów opartych na
jądrze Linux. Dotyczy to nie tylko sprzętu ta-
kiego jak netbooki, lecz również PDA i smart-
Listing 1.
Przykładowy wpis konfiguracyjny dla nowego jądra w programie rozruchowym GRUB
title Kernel 2.6.30.5 – nowy
# etykieta
root (hd0,0)
# dysk główny
kernel /boot/bzImage-2.6.30.5
root
= /dev/sda1 ro quiet
# ścieżka do
obrazu jądra i opcje
Listing 2.
Przykładowy wpis konfiguracyjny dla nowego jądra w programie rozruchowym LILO
image
=/boot/bzImage-2.6.30.5
# ścieżka do obrazu jądra
label
=Kernel 2.6.30.5 - nowy
# etykieta
read
-only
# tryb tylko do odczytu
root
=/dev/sda1
# partycja główna
32
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
33
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
fony. Przykładem mogą być chociażby platfor-
my Android oraz Moblin.
Przygotowanie
do kompilacji jądra
Zanim zajmiemy się omówieniem procesu
pobrania i instalacji najnowszej wersji jądra,
warto zastanowić się, jakie pakiety będą nam
potrzebne do jego konfiguracji oraz kompila-
cji. Po instalacji nowego jądra, często okazu-
je się również, że do poprawnej pracy syste-
mu konieczna jest aktualizacja pakietów wy-
mienionych poniżej.
Narzędzia kompilacji
Jeżeli jesteś początkującym użytkownikiem
systemu Linux, to z pewnością masz nieprzy-
jemne wspomnienia związane z kompilacją
programów ze źródeł. Błędy, które z pewno-
ścią często napotykałeś (zwłaszcza przy okazji
budowania mniej popularnych aplikacji) wy-
nikały z używania niewłaściwej wersji pakie-
tu GCC lub błędów samego programisty. Mam
przyjemność poinformować Cię, że w przy-
padku jądra, prawie na pewno nie napotkasz
żadnych problemów – jest to bowiem kod o
znaczeniu absolutnie krytycznym, dokładnie
przeanalizowany przez najlepszych programi-
stów na świecie. W celu sprawnej kompilacji
powinieneś jednak upewnić się, że dysponu-
jesz najnowszymi wersjami kilku pakietów, a
mianowicie: kompilatora GCC, narzędzi binu-
tils oraz programu make.
Jako że jądro Linux napisane jest w ję-
zyku C (ze wstawkami w asemblerze), bę-
dziesz potrzebował możliwie najnowszej
wersji kompilatora GCC. Jest on dostępny w
repozytoriach wszystkich dystrybucji, więc
na pewno nie będziesz miał problemów z je-
go instalacją.
Do przeprowadzenia kompilacji jądra,
będziesz również potrzebował pakietu binu-
tils, zawierającego narzędzia służące do ope-
rowania na plikach binarnych (m. in. linker i
asembler).
Program make wykorzystywany jest w
procesie automatycznej kompilacji i linkowa-
nia programów składających się z wielu pli-
ków źródłowych.
Programy zależne od jądra
Większość programów działających w prze-
strzeni użytkownika jest niezależna od uży-
wanej wersji jądra systemu. Istnieje jed-
nak pewna grupa aplikacji, które w znacz-
nym stopniu zależne są od działania pew-
nych mechanizmów jądra. Instalacja nowe-
go jądra może spowodować, że programy
te zaczną działać niepoprawnie lub w ogó-
le nie dadzą się uruchomić. Jeżeli po rekom-
pilacji jądra zauważyłeś problemy, powinie-
neś zainstalować nowsze wersje odpowied-
nich programów.
Część programów, które mogą wyma-
gać uaktualnienia po instalacji nowego ją-
dra, to:
• module-init-tools – narzędzia służące do
obsługi modułów jądra;
• udev – narzędzia służące do dynamiczne-
go tworzenia plików urządzeń w katalogu
/dev;
• util-linux – zbiór podstawowych narzę-
dzi wykorzystywanych w systemach
Linux;
• Narzędzia do obsługi systemów plików.
Pobranie najnowszej wersji jądra
Najnowsza wersja jądra Linux jest zawsze do-
stępna na stronie http://www.kernel.org/. Znaj-
dują się tam nie tylko pełne wersje źródeł, lecz
również tzw. patche – pliki umożliwiające ak-
tualizację posiadanych źródeł jądra. Więcej o
ich wykorzystaniu powiemy w następnej czę-
ści cyklu, kiedy zajmiemy się optymalizacją
konfiguracji jądra.
Po otworzeniu strony ze źródłami jądra
Linux, z pewnością zauważysz, że dostęp-
nych jest wiele różnych wersji, z których część
oznaczona jest jako stabilna, część jako wersje
testowe. Którą powinieneś wybrać?
Oznaczenia wersji jądra
W większości przypadków, najodpowiedniej-
szym rozwiązaniem będzie pobranie najnow-
szej stabilnej wersji jądra. Warto jednak po-
znać system oznaczeń wersji, aby mieć świa-
domość, w jaki sposób odbywa się rozwój tej
części systemu.
Jeżeli używałeś Linuksa jeszcze w cza-
sach jądra z rodziny 2.4, to z pewnością pa-
miętasz podział na dwie gałęzie: gałąź roz-
wojową (development) oraz stabilną (sta-
ble). Wersje testowe oznaczane były za po-
mocą liczby nieparzystej (np. 2.5.22), zaś
stabilne przy pomocy liczby parzystej (np.
2.4.22). Taki system oznaczeń powodował
jednak wiele niedogodności oraz był nie-
zbyt zrozumiały dla początkujących użyt-
kowników.
Wraz z wprowadzeniem jądra w wer-
sji 2.6 zdecydowano się zmienić sys-
tem numerowania wersji. Zrezygnowa-
no z utworzenia osobnej gałęzi dla wer-
sji rozwojowych, decydując się na wyko-
rzystanie schematu numeracji z wersjami
-rc (ang. release candidate). Nowy sche-
mat łatwo wytłumaczyć na przykładzie
(Rysunek 3). Załóżmy, że ukazuje się wer-
sja 2.6.30 jądra. W trakcie prac, dewelo-
perzy odnajdują błędy, które zostają usu-
nięte w kolejnych wersjach stabilnych ją-
dra, oznaczanych jako 2.6.30.1, 2.6.30.2
itd. W tym samym czasie, trwają intensyw-
ne prace nad nowymi funkcjami, wskutek
czego powstają wersje testowe, oznaczane
2.6.31-rc1, 2.6-31-rc2 itd. Po kilku miesią-
cach, wersja 2.6.31-rcX zostaje uznana za
stabilną i cykl powtarza się.
Pobranie i rozpakowanie jądra
Zdecydowanie polecam Ci pobranie najnow-
szej dostępnej wersji stabilnej jądra. Mo-
żesz tego dokonać wchodząc na stronę http:
//www.kernel.org/ i klikając w link Full Source
znajdujący się obok najnowszej wersji ozna-
czonej jako stable (Rysunek 4). Źródła jądra
zajmują około 55 MB.
Jeżeli chcesz pobrać źródła w trybie tek-
stowym, to możesz tego dokonać za pomo-
cą polecenia:
wget http://kernel.org/pub/linux/
kernel/v2.6/linux-2.6.x.x.tar.gz
Aby wyświetlić informacje o najnowszych
wersjach jądra, możesz skorzystać z poleceń:
wget http://kernel.org/kdist/finger_
banner
cat finger_banner
Po pobraniu, źródła możesz rozpakować przy
użyciu polecenia:
tar -xzvf linux-2.6.x.x.tar.gz ~/
linux-src/
Zapoznamy się teraz ze strukturą katalogów ze
źródłami jądra Linux.
Struktura katalogów ze źródłami
Po rozpakowaniu archiwum ze źródłami, z
pewnością zauważysz, iż zajmują one łącznie
ponad 300 MB. Taka ilość kodu może przy-
tłaczać, w znakomitej większości są to jednak
komponenty, których nie będziesz wykorzy-
stywał w swoim systemie. Przyjrzyjmy się te-
raz zawartości najistotniejszych katalogów w
drzewie jądra:
• arch – pliki zawierające implementacje
funkcji charakterystycznych dla konkret-
nych architektur sprzętowych obsługiwa-
nych przez jądro;
• crypto – pliki zawierające implementacje
mechanizmów kryptograficznych jądra;
34
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
35
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
• drivers – pliki z kodem źródłowym ste-
rowników urządzeń;
• firmware – pliki z kodem źródłowym ob-
sługi firmware urządzeń;
• fs – pliki zawierające implementacje sys-
temów plików;
• init – pliki zawierające implementacje
funkcji niezbędnych do rozruchu systemu;
• ipc – pliki zawierające implementację me-
chanizmów komunikacji międzyproceso-
wej (semafory, kolejki wiadomości itp.);
• kernel – pliki zawierające implementację
najważniejszych funkcji jądra (obsługa
przerwań, schedulera itp.);
• mm – pliki zawierające implementację
mechanizmów związanych z zarządza-
niem pamięcią;
• net – pliki zawierające implementację
mechanizmów sieciowych jądra;
• security – pliki zawierające implementa-
cję mechanizmów zabezpieczeń jądra;
• sound – pliki zawierające implementację
mechanizmów obsługi dźwięku;
• virt – pliki zawierające implementację
mechanizmów obsługi wirtualizacji.
W głównym katalogu źródeł jądra znajdują się
również katalogi Documentation (dokumenta-
cja jądra), include (pliki nagłówkowe jądra),
oraz lib (implementacja funkcji bibliotecz-
nych jądra).
Konfiguracja jądra
Przed rozpoczęciem kompilacji powinieneś
wybrać komponenty, które chcesz zbudować
jako część statyczną jądra oraz moduły. Archi-
wum ze źródłami jądra, które przed chwilą po-
brałeś z internetu, zawiera również wygodne
narzędzia, pozwalające na szybką modyfika-
cję konfiguracji.
Konfigurację jądra możemy przeprowa-
dzić na trzy sposoby:
• Odpowiadając na pytania odnośnie każ-
dego składnika jądra – szczerze odra-
dzam Ci zastosowanie tej metody, przy-
najmniej na początku. Proces ten jest bo-
wiem niezwykle czasochłonny (należy
odpowiedzieć na ponad 2000 pytań) oraz
wymaga dużej wiedzy na temat poszcze-
gólnych elementów jądra;
• Korzystając z narzędzia działającego
w trybie tekstowym – w takim przy-
padku zaczynamy pracę od wczytania
standardowej konfiguracji oraz urucho-
mienia narzędzia menuconfig (Rysunek
5). Jest to zdecydowanie najlepsze roz-
wiązanie, gdy budujemy jądro na zdal-
nym systemie, np. przy użyciu połą-
czenia SSH. Należy pamiętać, iż w ce-
lu kompilacji i uruchomienia programu
menuconfig potrzebna jest biblioteka
ncurses;
• Korzystając z narzędzia działającego w
trybie graficznym – podobnie jak w przy-
padku programu menuconfig, zaczynamy
od wczytania konfiguracji domyślnej, a
następnie wprowadzamy w niej zmia-
ny przy użyciu narzędzia działającego w
trybie graficznym (Rysunek 6). Mamy do
wyboru dwa programy: jeden z nich ko-
rzysta z biblioteki QT3 (xconfig), drugi z
GTK+ (gconfig).
W tym artykule omówimy dwa ostatnie z wy-
mienionych sposobów konfiguracji.
Część statyczna a moduły
Większość elementów jądra możemy zbudo-
wać jako składnik części statycznej lub jako
moduł. Jaka jest różnica pomiędzy tymi dwo-
ma rozwiązaniami i czym powinniśmy kiero-
wać się przy podjęciu decyzji?
Moduł jest skompilowanym elementem
jądra, który możemy wczytać w dowolnym
momencie po uruchomieniu systemu ope-
racyjnego (za pomocą programu modpro-
be). Gdy zdecydujemy, że wczytany do pa-
mięci moduł jest nam już niepotrzebny, mo-
żemy go usunąć. Moduły w systemie Linux
przechowywane są zazwyczaj w katalogu
/lib/modules jako pliki obiektowe z rozsze-
rzeniem .ko. Listę obecnych w systemie mo-
dułów, wraz z podstawowymi informacjami
na ich temat, możesz uzyskać przy pomocy
polecenia
lsmod
.
Część statyczna jądra (ang. base ker-
nel) to część jądra, która jest zawsze obec-
na w pamięci – nie możemy jej odłączyć.
Co więcej, dokonanie jakichkolwiek zmian
w jej obrębie wymaga ponownego urucho-
mienia systemu, a często nawet rekompila-
cji całego jądra. W części statycznej znaj-
duje się zdecydowana większość kodu, od-
powiadającego za realizację podstawowych
funkcji systemu.
Wybór składników
Po zapoznaniu się w podanymi informacja-
mi, możesz przejść do konfiguracji jądra.
Zastosujemy tu wygodną metodę, polega-
jącą na wczytaniu konfiguracji domyślnej,
a następnie wprowadzeniu modyfikacji w
obrębie interesujących nas funkcji. Pamię-
taj, aby wykonywać te czynności przy uży-
ciu konta użytkownika bez uprawnień admi-
nistratora – w przeszłości zdarzały się bo-
wiem błędy, które powodowały uszkodze-
nie ważnych plików systemowych w trakcie
kompilacji jądra.
Aby wczytać domyślną konfigurację ją-
dra, przejdź do katalogu z źródłami i wpro-
wadź polecenie:
make defconfig
Następnie, w celu uruchomienia programu
konfiguracyjnego działającego w trybie gra-
ficznym (GTK+), wydaj polecenie:
make gconfig
Jeżeli wolisz skorzystać z narzędzia wykorzy-
stującego bibliotekę QT3, możesz wydać po-
lecenie:
make xconfig
Po chwili, w czasie której narzędzie konfigura-
cyjne jest kompilowane, Twoim oczom ukaże
się program, w którym będziesz mógł zmienić
ustawienia jądra.
Opcje konfiguracyjne zostały podzielone
na następujące kategorie:
• General setup – kategoria zawierająca
podstawowe opcje konfiguracyjne ją-
dra;
• Processor type and features – kategoria
zawierająca opcje konfiguracyjne wpły-
wające na obsługę procesora. Niektó-
re ze znajdujących się tu opcji dotyczą
wsparcia konkretnych technologii (np.
SMP) lub aktualizacji mikrokodu pro-
cesora;
• Power management and ACPI options
– kategoria zawierająca opcje konfigura-
cyjne dotyczące funkcji zarządzania ener-
gią oraz ustawienia systemu ACPI;
• Bus options (PCI etc.) – kategoria zawie-
rająca opcje konfiguracyjne obsługi magi-
strali, takich jak PCI, PCI-E;
• Executable file formats/Emulations – ka-
tegoria pozwalająca na wybór obsługiwa-
nych przez jądro typów plików wykony-
walnych;
• Strona główna jądra Linux – http://www.kernel.org/
• Strona KernelTrap – http://kerneltrap.org/
W Sieci
34
listopad 2009
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
35
www.lpmagazine.org
Jądro Linuksa
Linux Kernel (1/7): Wprowadzenie, kompilacja i instalacja
• Networking support – kategoria zawiera-
jąca opcje konfiguracyjne związane z pra-
cą różnego rodzaju urządzeń sieciowych
oraz stosu TCP/IP;
• Device Drivers – kategoria umożliwiająca
wybór sterowników urządzeń, które chce-
my włączyć do części statycznej jądra lub
skompilować jako moduły;
• Firmware Drivers – kategoria zawiera-
jąca opcje dotyczące obsługi firmware
urządzeń;
• File Systems – kategoria umożliwia-
jąca wybór obsługiwanych systemów
plików;
• Kernel hacking – kategoria zawierająca
rozmaite opcje konfiguracyjne, przydatne
przy modyfikacji kodu jądra oraz tworze-
niu własnych modułów;
• Security options – kategoria zawierająca
opcje konfiguracyjne wpływające na za-
bezpieczenia wykorzystywane w syste-
mie;
• Cryptographic API – kategoria zawierają-
ca opcje konfiguracyjne interfejsu krypto-
graficznego jądra systemu;
• Virtualization – kategoria zawierająca
opcje związane z technologią wirtuali-
zacji;
• Library routines – kategoria zawierająca
opcje konfiguracyjne funkcji bibliotecz-
nych.
Dla każdego ze składników jądra możesz wy-
brać jedną z trzech opcji: nieaktywny (N), zbu-
dowany jako moduł (M), wbudowany w część
statyczną (Y).
Po zmianie interesujących Cię opcji kon-
figuracyjnych, możesz zapisać zmiany korzy-
stając z przycisku Save.
Kompilacja jądra
Sam proces kompilacji nie powinien po-
wodować żadnych problemów – jeżeli tak
się dzieje, znaczy to, że powinieneś spraw-
dzić, czy używasz najnowszych wersji na-
rzędzi wymienionych we wcześniejszej czę-
ści artykułu.
Aby rozpocząć kompilację jądra, należy
wydać polecenie:
make
Jeżeli korzystasz z procesora wielordzenio-
wego, możesz znacznie skrócić czas kompi-
lacji, dzięki zastosowaniu opcji konfiguracyj-
nej
-jN
, gdzie
N
to liczba procesorów pomno-
żona przez 2, np.
make -j4
Po zakończeniu procesu kompilacji, możesz
przejść do następnego kroku, którym jest in-
stalacja modułów.
Instalacja modułów
Po zakończeniu procesu kompilacji jądra, na-
leży zainstalować moduły przy pomocy pole-
cenia:
make modules_install
Do jego poprawnego wykonania niezbędne są
uprawnienia użytkownika root.
Instalacja jądra
W trakcie procesu instalacji wygenerowa-
ny zostaje plik z obrazem jądra, który zosta-
je wczytany do pamięci przez program rozru-
chowy. W celu umożliwienia wyboru nowego
jądra w trakcie uruchamiania systemu, prze-
kopiujemy jego obraz do katalogu /boot oraz
odpowiednio zmodyfikujemy pliki konfigura-
cyjne boot loader'a. Opiszemy tu procedurę
dla programu rozruchowego GRUB, jednak
w przypadku LILO przebiega ona bardzo po-
dobnie (Listing 2). W razie wątpliwości, od-
wołaj się do dokumentacji wykorzystywane-
go programu.
Po zakończeniu procesu kompilacji,
obraz jądra znajduje się w pliku ~/kernel-
src/linux-2.6.x.x/arch/x86/boot/bzImage.
Przekopiuj go do katalogu /boot za pomo-
cą polecenia:
cp ~/kernel-src/linux-2.6.x.x/arch/
x86/boot/bzImage /boot/bzImage-
2.6.x.x
Oprócz tego, konieczne jest również prze-
kopiowanie pliku ~/kernel-src/linux-2.6.x.x/
System.map do katalogu /boot:
cp ~/kernel-src/linux-2.6.x.x/
System.map /boot/System.map-2.6.x.x
Następnym krokiem jest konfiguracja pro-
gramu rozruchowego. W przypadku pro-
gramu GRUB jest ona bardzo prosta i pole-
ga na dodaniu nowego wpisu na końcu pliku
/boot/grub/menu.lst. Przykładowy wpis został
przedstawiony na Listingu 1.
Po wykonaniu wszystkich opisanych
czynności, możesz ponownie uruchomić kom-
puter i wybrać nowe jądro w menu programu
rozruchowego.
Kernel panic?
W trakcie lektury tego cyklu z pewnością spo-
tkasz się z sytuacją, w której nowe jądro od-
mówi posłuszeństwa, wyświetlając przy star-
cie ogromne ilości komunikatów o błędach,
podsumowane krótkim napisem Kernel pa-
nic. Nie powinieneś się tym jednak przejmo-
wać – wystarczy zresetować komputer oraz
wybrać z menu programu rozruchowego dzia-
łający obraz jądra.
Istnieje wiele przyczyn, które mogą po-
wodować powstanie błędów uniemożliwiają-
cych uruchomienie systemu z nowym jądrem.
Nie sposób wymienić tu wszystkich, jednak
jego wystąpienie zawsze świadczy o tym, że
na którymś z opisanych w artykule etapów po-
pełniłeś błąd. Bardzo często Kernel panic jest
skutkiem wadliwej konfiguracji programu roz-
ruchowego.
Podsumowanie
Tym sposobem dotarliśmy do końca pierw-
szej części cyklu. Zapoznałeś się w nim z ar-
chitekturą nowoczesnego systemu operacyj-
nego, różnymi metodologiami budowy ją-
dra oraz jego zadaniami. Omówiliśmy krót-
ko historię jądra Linux oraz jego wpływ na
rozwój ruchu Wolnego Oprogramowania,
poznaliśmy podstawowe cechy jego budo-
wy oraz architektury, na których działa. Do-
wiedziałeś się również, w jaki sposób po-
brać najnowszą wersję jądra, dokonać je-
go konfiguracji, rekompilacji oraz instala-
cji w systemie.
Jeżeli jesteś zainteresowany szczegóła-
mi związanymi z działaniem jądra systemu
operacyjnego oraz jądrem Linux, to polecam
Ci odwiedzenie stron wymienionych w tabe-
li W Sieci. Znajdziesz tam wiele informacji
na tematy, dla których zabrakło miejsca w
tym artykule.
W następnej części cyklu zajmiemy się
bliżej procesem optymalizacji jądra poprzez
wybór odpowiednich składników, odpowia-
dających naszym potrzebom. Dowiesz się
również, w jaki sposób możesz skrócić czas
uruchamiania systemu oraz zapoznasz się ze
szczegółami procesu uruchamiania systemu
Linux. Do usłyszenia!
Autor interesuje się bezpieczeństwem
systemów informatycznych, programo-
waniem, elektroniką, muzyką rockową,
architekturą mikroprocesorów oraz za-
stosowaniem Linuksa w systemach wbu-
dowanych.
Kontakt z autorem: rl.kulaga@gmail.com
O autorze