Jądro i system plików w OS Linux.doc

(86 KB) Pobierz
Jądro i system plików

Jądro i system plików

 

W czasie pierwszej instalacji systemu instalowane jest na dysku standardowe jądro dystrybucyjne. Jądro to działa z reguły bez zarzutu, a wraz z dołączonymi modułami powinno nam zapewnić obsługę wszystkich urządzeń. Takie standardowe nie zawsze będzie jednak optymalnie dopasowane do naszego systemu. Najczęściej będzie zbyt duże, ponieważ obsługuje urządzenia, które nie występują w naszym sprzęcie, a także często funkcję i obsługi z których nie korzystamy. Nie będzie poza tym wykorzystywać optymalnie szczególnych cech procesora, jaki mamy w komputerze itd.
Jeżeli oczekujemy od naszego systemu maksymalnej wydajności, powinniśmy indywidualnie dopasować jądro do naszych potrzeb, to znaczy skonfigurować je (określić jego cechy i funkcje) i skompilować. Teksty źródłowe potrzebne do kompilacji powinniśmy otrzymać wraz z dystrybucją systemu bądź pozyskać z innych źródeł.
Raz zainstalowane (skonfigurowane i skompilowane) jądro nie wymaga pielęgnacji. Jednakże w dłużej funkcjonującym systemie zechcemy zwykle po jakimś czasie wymienić jądro na nowszą wersję bądź połatać starą. Nowa wersja może oferować nowe możliwości bądź obsługę określonych urządzeń, których stara wersja nie obsługuje. Łaty na starą wersję oferują zwykle usunięcie wykrytych błędów i czasami obsługę pewnych nowych urządzeń.
Zainstalowanie nowej wersji jądra sprowadza się do pozyskania tekstów źródłowych, skonfigurowania i skompilowania jądra. Należy jednak pamiętać, że zupełnie nowa wersja jądra (nawet jeżeli kompilacja przebiegnie bezproblemowo) może okazać się eksperymentem, który wymaga weryfikacji w naszym konkretnym systemie. Jądro musi być bowiem zgodne z innym oprogramowaniem systemowym. Z uwagi na ciągłe dynamiczne zmiany i rozwój Linuksa (w szczególności samego jądra), nie możemy "pierwszej lepszej" najnowszej wersji jądra (np.2.2.16) wyrwać z kontekstu i próbować osadzić bezceremonialnie w systemie, który do tej pory pracował na innym jądrze, na przykład 2.0.16 lub starszym. W takim przypadku należy zdecydować się raczej na aktualizację (ang. upgrade) całego systemu wraz z jądrem. Na szczęście Linux jest systemem darmowym, więc aktualizacja nie obciąży nas finansowo :-) Nie mniej jednak, jeżeli mamy "dopieszczony" dłuższy czas funkcjonujący bezproblemowo system, jego aktualizacja może spowodować, że będziemy musieli ponownie borykać się z problemami, które uważaliśmy już za rozwiązane. Program instalacyjny w dystrybucji Red Hat oferuje automatyczną aktualizację, jednak mimo wszystko wcześniej warto zapoznać się z dokumentami HOWTO, pod tytułem Upgrade (www.jtz.org.pl). Dotyczy on wprawdzie dystrybucji Slackware, ale poruszane w niej problemy są uniwersalne. Wymiana samego jądra jest najbezpieczniejszą i najmniej kłopotliwą aktualizacją (o ile nowe jądro pasuje od reszty systemu).
Dobrym zwyczajem jest przestrzeganie zasady instalowania w systemie jąder generacji, do której system został przystosowany. Przypomnijmy sobie, że jądra z parzystą środkową cyfrą w oznaczeniu (np. x.0.x, x.2.x itd.) są tak zwanymi wersjami stabilnymi, a te z nieparzystą (np. x.1.x, x.3.x itd.) są wersjami rozwojowymi (niestabilnymi), przeznaczonymi do testowania.
System plików jest automatycznie weryfikowany i pielęgnowany (przynajmniej w elementarnym zakresie) przez procedury wykonywane w trakcie uruchamiania Linuksa. Ta metoda jest z reguły wystarczająca, nawet jeżeli zaszły niespodziewane, gwałtowne wydarzenia. Takim wydarzeniem może być przykładowo zanik napięcia zasilającego bądź bezceremonialne wyłączenie komputera bez uprzedniego zamknięcia (shutdown) systemu.

Moduły jądra (lsmod, insmod, rmmod)

Jądro systemu może być skonfigurowane do pracy z modułami (ang. modules support) albo, niezmiernie rzadko, jako monolityczne, czyli nie wykorzystujące modułów. Moduły są to fragmenty jądra odpowiedzialne głównie za obsługę konkretnych urządzeń (np. sterowniki kart sieciowych), które są w miarę aktualnych potrzeb dołączane i odłączane od zasadniczej części jądra. Może się to odbywać dynamicznie, czyli w trakcie pracy systemu.
W dobrze skonfigurowanym systemie możemy nic nie wiedzieć o istnieniu modułów, ponieważ istnieje narzędzie, które automatycznie ładuje u wyrzuca moduły. Tym narzędziem jest demon kerneld (kernel daemon). Demony są usługowymi programami systemowymi stale obecnymi w pamięci i będącymi w każdej chwili na nasze usługi.
Istnieje także możliwość ręcznego zarządzania modułami. Może być ona przydatna przy eksperymentowaniu z nowymi urządzeniami, ale także przy rozwiązywaniu różnych problemów poprawnym działaniu systemu.
W typowej dystrybucji Linuksa jądro zawsze będzie obsługiwało moduły i będzie dostarczone z dużym ich arsenałem. W naszym przypadku moduły jądra znajdują się w katalogu /lib/modules/2.0.36-07. Katalog ten zawiera podkatalogi grupujące moduły pod względem przeznaczenia. W podkatalogu net znajdziemy szereg plików z przyrostkami .o w nazwie. Są to właśnie moduły jądra, oto niektóre z nich:

 

3c503.o     -  sterownik kart sieciowych Ethernet 3COM Etherlink II (3c503)

3c509.o     -  sterownik kart sieciowych Ethernet 3COM Etherlink II (3c509)

tulip.o     -  sterownik kart sieciowych opartych o układ DEC 2104x i 2114x,

               np. D-Link DE-530CT+

 

 

W podkatalogu misc (rozmaitości) znajdziemy międzu innymi:

 

gus.o       -  sterownik kart dźwiękowych Gravis Ultrasound

 

w podkatalogu fs (systemy plików):

 

vfat        -  sterownik obsługujący system plików vfat

 

Listę modułów aktualnie zainstalowanych możemy zobaczyć za pomocą polecenia:

 

# lsmod

 

Module                  Pages                               Used by

tulip                       6                                     1 (autoclean)

[root@crash /root]# _

 

Instalowanie modułu dokonujemy poleceniem:

insmod nazwa_modułu

a usunięcia:

rmsmod nazwa_modułu

Zarówno zainstalowanie, jak i usunięcie zostanie dokonane po spełnieniu szeregu warunków. W szczególności z odmową spotka się polecenie usunięcia modułu, który jest "zajęty" bądź wymagany przez inne moduły. Spróbujemy praktycznie zainstalować i zdeinstalować określony moduł:

 

# insmod  vfat

[root@crash /root]# lsmod

Module                  Pages                               Used by

vfat                        4                                     0

tulip                       6                                     1 (autoclean)

[root@crash /root]# rmmod

[root@crash /root]# lsmod

Module                  Pages                               Used by

tulip                       6                                     1 (autoclean)

[root@crash /root]# _

Konfigurujemy i kompilujemy jądro (make)

W katalogu /usr/scr/redhat/SOURACES znajdziemy plik zawierający źródła jądra (w naszym przypadku linux-2.0.36.tar.gz), który można rozpakować.

 

# cd /usr/src/linux

[root@crash linux]# less README

...

...

[q]

[root@crash linux]# cd /usr/include

[root@crash include]# rm -rf asm linux scsi

[root@crash include]# ls -s /usr/src/linux/include/asm-i386   asm

[root@crash include]# ls -s /usr/src/linux/include/linux   linux

[root@crash include]# ls -s /usr/src/linux/include/scsi   scsi

[root@crash include]# cd /usr/src/linux

[root@crash linux]# make mrproper

...

...

rm -f /usr/src/linux/include/linux/modules/*

[root@crash /root]# _

Plik README zawiera dokładny opis procedury kompilacji jądra, wystarczy więc go tylko przeczytać.
W pierwszej kolejności sprawdzamy istnienie w katalogu /usr/includes odpowiednich dowiązań symbolicznych (asm, linux i scsi). Najlepiej jest usunąć stare dowiązania i założyć odpowiednie nowe. Po tym zabiegu wykonujemy generalne porządki (make mrproper) i jesteśmy gotowi do konfiguracji jądra. Możemy tego dokonać za pomocą jednego z trzech narzędzi, wywoływanych odpowiednio:

 

make config - prosty tekstowy konfigurator, w którym zmuszeni jesteśmy do uciążliwych odpowiedzi na serię kolejnych pytań, kłopotliwy w użyciu i koszmarny dla początkujących

make menuconfig - semigraficzny konfigurator z czytelnym menu i systemem pomocy, praktyczny i elastyczny

make xconfig - konfigurator z interfejsem graficznym (wymaga X-Windows)

 

Osobiście preferuję menuconfig, gdyż jest proste i wygodne w obsłudze i nie potrzebuje do pracy X-Windows. Optymalna i sensowna konfiguracja jądra wymaga nieco wiedzy nie tylko o systemie, ale także o sprzęcie, określonych standardach itd. Niewłaściwie skonfigurowane jądro może nie realizować niektórych funkcji (np. obsługa sieci), nie obsługiwać urządzeń itd. Możemy jednak wprowadzając poprawki do konfiguracji jądra i kompilując kolejne jego wersje (nawet metodą prób i błędów) dopracować się funkcjonującej i optymalnej wersji jądra. W trakcie takich eksperymentów należy przestrzegać:

 

- nie usuwać starej wersji jądra z systemu

- tak skonfigurować program LILO, aby istniała możliwość wyboru jądra przy starcie systemu, co pozwoli nam uruchomić system ze starym jądrem, gdy nowe nie będzie działało

 

Pamiętajmy, że konfiguracja jądra odbywa się w katalogu /usr/src/linux i wszelkie polecenia make musza być wydawane z poziomu tego katalogu.

Menu config jest semigraficznym konfiguratorem o prostej i wygodnej obsłudze. Poprzez naciśnięcie [Enter] rozwijamy odpowiednią pozycję głównego menu i następnie zaznaczamy (usuwany zaznaczenie) odpowiednie parametry jądra naciskając klawisz spacji.
Jeżeli przy opuszczaniu (Exit) menuconfig na pytanie czy chcemy zachować ustawienia (Do you wish to save your new kernel configuration?) odpowiedzmy twierdząco (Yes), wówczas zostanie utworzony w bieżącym katalogu ukryty plik .config zawierający naszą konfigurację. Plik ten jest wykorzystywany do kompilacji. Przy kolejnym uruchomieniu menuconfig wszystkie ustawienia pobierane są właśnie z tego pliku. Jest to niezwykle wygodne przy wielokrotnej kompilacji jądra. Oprócz pozycji głównego menu dotyczących parametrów jądra, mamy jeszcze dwie dodatkowe:

 

1. Load an Alternate Configuration File

2. Save Configuration to an Alternate File

 

Pozycja druga umożliwia zapisanie bieżącej konfiguracji do pliku o zadanej przez nas nazwie (innej niż .config). W ten sposób możemy przygotować wiele różnych konfiguracji do późniejszego wykorzystania. Pozycja pierwsza umożliwia załadowanie takiego właśnie pliku do menuconfig.
Po skonfigurowaniu jądra i zapisaniu tej konfiguracji w pliku .config możemy przystąpić do kompilacji. Uruchomienie kompilacji w sytuacji gdy plik .config nie istnieje spowoduje automatyczne wywołanie domyślnego konfiguratora (config), który zacznie nam zadawać pytania. Taką sytuację można przerwać kombinacją klawiszy [Ctrl]+[c].
 

Kompilacja jądra na moim komputerze potrwała około 9 minut:

[root@crash linux]# make dep

...

...

mv .tmpdepend .depend

[root@crash linux]# make clean

...

...

rm -f submenu*

[root@crash linux]# make zImage

...

...

make[1]: Leaving directory '/usr/src/linux/arch/i386/boot'

[root@crash linux]# _

Make dep służy do sprawdzania spójności tekstu źródłowego. Natomiast make clean usuwa pozostałości po ostatniej kompilacji. Polecenie make zImage jest właściwym poleceniem kompilacji. Skompilowane jądro jest umieszczane w katalogu /usr/src/linux/arch/i386/boot.

Po dokonaniu kompilacji jądra powinniśmy jeszcze skompilować i zainstalować moduły jądra. Robimy to dwoma kolejnymi poleceniami:

 

# make modules

# make modules_install

 

W wyniku powyższych dwóch poleceń skompilowane moduły jądra powiny znaleźć się w katalogu /lib/modules/nr_wersji_jądra. W naszym przypadku powinien to być katalog /lib/modules/2.0.36. Korzystanie z modułów jest obligatoryjne. W szczególności jeżeli w menuconfig wyłączymy parametr Enable loadable module support (występujący w pozycji Loadable module support głównego menu), nie musimy kompilować modułów, natomiast obsługa wszystkich urządzeń (np. kart sieciowych) musi być ustawiona jako wbudowana w zasadniczą cześć jądra.
W przypadku gdy kompilacja zakończyła by się błędem wynikającym ze zbyt dużych rozmiarów jądra, należy ją powtórzyć używając polecenia: make bzImage
Skompilowane jądro kopiujemy do katalogu, w którym system przechowuje obraz jądra (w naszym przypadku jest to katalog /boot). Przy okazji zmieniamy jego nazwę na vmlinuz.nowe. Następną czynnością będzie zmodyfikowanie pliku konfiguracyjnego LILO (/etc/lilo.conf). Otwieramy ten plik do edycji i znajdujemy w nim sekcję:

 

image=/boot/vmlinuz-2.0.36-0.7

         label=linux

         root=/dev/hda1

         read-only

 

Dodajmy poniżej analogiczną sekcję, różniącą się nazwą obrazu jądra i etykietą (ang. label):

 

image=/boot/vmlinuz.nowe

         label=nowe

         root=/dev/hda1

         read-only

 

W ten sposób loader ma do dyspozycji dwa alternatywne jądra (określane przez etykiety: "linux" i "nowe"). Wybory jądra dokonywać będziemy przy starcie systemu. Aby jednak modyfikacja pliku /etc/lilo.conf weszła w życie, musimy je zapisać poleceniem:

 

# lilo

Added linux *

Added nowe

Added win

 

Gwiazdka przy nazwie "linux" oznacza, że jądro opatrzone tą etykietą będzie ładowane domyślnie.
Po zakończeniu testowania, gdy upewnimy się już, że nasze nowe jądro funkcjonuje prawidłowo, możemy usunąć zbędną sekcję z lilo.conf bądź ustawić etykietę "nowe" jako domyślną.

Łatamy jądro (patch)

Łatanie jądra sprowadza się do założenia dostarczonej łaty na posiadane teksty źródłowe aktualnie używanego jądra i następnie skonfigurowaniu i skompilowaniu jądra w oparciu o "połatane" teksty źródłowe. Tekst źródłowy jądra znajduje się w katalogu /usr/src/linux. Otrzymany plik z łatą kopiujemy do katalogu /usr/src/ i tutaj dokonamy nałożenia łaty poleceniem:

 

# patch -p0 < pliklata

albo na przykład:

# cat pliklata | patch -p0

 

Jeżeli plik z łatą jest skompresowany (posiada przyrostek .gz) musimy go wcześniej zdekompresować (gunzip pliklata.gz) bądź także skorzystać z potoku:

 

# gzip -dc pliklata.gz | patch -p0

Opcję -p0 poznaliśmy już w ćwiczeniu Archiwa i łaty . Polecenie patch w przypadku problemów z właściwym nałożeniem łaty generuje pliki z przyrostkiem .rej w nazwie. Zasadnicza część nazwy takiego pliku odpowiada rzeczywistemu plikowi, z którym były trudności. Aby przekonać się, czy łata została nałożona prawidłowo, musimy przeskanować rekurencyjnie katalog /usr/src/linux w poszukiwaniu plików z przyrostkiem .rej. Możemy to zrobić tak:

 

# find  /usr/src/linux -name "*.rej"

 

Jeżeli wynik poszukiwań okaże się negatywny, uznajemy, że łata jest nałożona prawidłowo i dokonujemy kompilacji jądra.

Sprawdzamy system plików (fsck, e2fsck)

Do sprawdzenia systemu plików administrator (root) używa polecenia fsck, które ma zastosowanie do różnych systemów plików, także do ext2 oraz e2fsck, które jest wyspecjalizowane do linuksowego systemu plików ext2. Obydwa dokonują sprawdzenia plików i potrafią naprawić automatycznie znalezione błędy. Może być uruchamiany w trybie interaktywnym (w przypadku wykrycia błędów zadają pytanie administratorowi prosząc go o decyzję) lub w trybie nieinteraktywnym.
W Linuksie musimy dysponować co najmniej jednym (głównym) systemem plików (montowanym jako /). System plików skojarzony jest fizycznym urządzeniem najczęściej partycją dysku twardego (np hda1), ale może to być dyskietka (fd0) lub CD-ROM (u mnie hde).
Sprawdzenie systemu plików wymaga jego odmontowania od głównego systemu plików. W naszym (najprostszym) przypadku dysk zawiera jednak tylko jedną partycję (hda1) właśnie z głównym systemem plików (oczywiście jest jeszcze partycja swap). W trakcie startu systemu możemy zaobserwować na ekranie, że nasz głównym system plików przed zamontowaniem jest weryfikowany i ewentualnie automatycznie (bez zadawanych pytań - opcja -a>) naprawiany poleceniem fsck.ext2 -a /dec/hda1 . Możemy łatwo sprawdzić:

 

# cmp /sbin/e2fsck  /sbin/fsck.ext2

[root@crash linux]# _

 

że e2fsck i fsck.ext2 to identyczne pliki. Wydając polecenie:

 

# ls -li e2fsck  fsck.ext2

42700  -rwxr-xr-x  2  root  root  274600  Aug  29 1998  e2fsck

42700  -rwxr-xr-x  2  root  root  274600  Aug  29 1998  fsck.ext2

[root@crash linux]# _

 

przekonamy się, ze pliki te posiadają ten sam numer -węzła (42700), co oznacza, że są dowiązaniami sztywnymi do tego samego fizycznie pliku.

Aby bezpiecznie i bezproblemowo przetrenować użycie polecenia fsck i e2fsck, wykorzystamy dyskietkę, na której założymy odpowiedni system plików. Przygotujemy więc dyskietkę i wkładamy ją do napędu:

 

# /dev/fdoH1440

Double-side,  80 tracks,  18 sec/track/ Total capacity 1440 kB.

Formating ... done

Veryfing ... done

[root@crash linux]# mke2fs  /dev/fd0

mke2fs  1.12,  9-Jul-98 for EXT2 FS 0.5b,  95/08/09

Linux ext2 filesystem format

Filesystem label=

360 inodes,  1440 blocks

72 blocks (5.00%) reserved for the super user

First data block=1

Block size=1024 (log=0)

Fragment size=1024 (log=0)

1 block group

8192 block per group,  8192 fragments per group

360 inodes per group

 

Writinf inode tables: done

Writinf superblocks and filesystem accounting information: done

[root@crash linux]# mount /mnt/floppy

[root@crash linux]# cp /etc/mtab  /mnt/floppy/mtabcop

[root@crash linux]# ls -aF  /mnt/floppy

./            ../            lost+found/            mstabcop

[root@crash linux]# mount

/dev/hda1  on  /  type  ext2  (rw)

none  on  /proc type proc  (rw)

/dev/fd0  on  /mnt/floppy  type  ext2  (rw)

[root@crash linux]# umount /mnt/floppy

[root@crash linux]# mount

/dev/hda1  on  /  type  ext2  (rw)

none  on  /proc type proc  (rw)

[root@crash linux]# e2fsck  -vnf  /dev/fd0

e2fsck 1.12,  9-Jul-98  for  EXT2  FS  0.5b,  95/08/09

Pass 1: Checking inodes, blocks, and size

Pass 2: Checking directory structure

Pass 3: Checking directory connectivity

Pass 4: Checking reference counts

Pass 1: Checking group summary information

 

            12  inodes uses (3%)

             0  non-contiguous inodes (0.0%)

                # of inodes with ind/dind/tind blocks: 0/0/0

            64  block used(4%)

             0  bad blocks

                                         

             1  regular file

             2  directory

             0  character device files

             0  block device files

             0  fifos

             0  links

             0  symbolic links (0 fast symbolic links)

             0  socket

------------

             3  files

[root@crash linux]# e2fsck  /dev/fd0

e2fsck 1.12,  9-Jul-98  for  EXT2  FS  0.5b,  95/08/09

/dev/fd0:  clean,  12/360  files,  64/1440  blocks

[root@crash linux]# _

 

Zwróćmy uwagę, że polecenie mount wydane bez żadnych parametrów powoduje wypisanie aktualnie zamontowanych systemów plików. Pozwala to nam sprawdzić, czy dyskietka została faktycznie odmontowana po wydaniu polecenia umount. Do sprawdzenia systemu plików na dyskietce posłużyliśmy się e2fsck wydanym z trzema opcjami. Dla porównania widzimy rezultat wykonania e2fsck /dev/fd0 (bez żadnych opcji). Wyjaśnijmy

znaczenie poszczególnych opcji:

 

-v - (verbose) - podaje rozszerzoną informację. W naszym przypadku jest to komunikat zaczynający się od wiersza "12 inodes used (3%)

-n - (no) - na wszystkie ewentualne pytani odpowiadamy "nie". Opcja ta umożliwia uruchomienie e2fsck w bezpiecznym trybie nieinteraktywnym. Istnieje również przeciwstawna opcja -y (yes), która odpowiada na wszystkie pytania "tak"

-f - (force) - wymusza sprawdzanie systemu plików, nawet wówczas gdy na pierwszy rzut oka wydaje się on czysty (clean)

 

Istnieje jeszcze jednak opcja -c (...

Zgłoś jeśli naruszono regulamin