Poniźszy opis odnosi się do Linuksa w wersji 2.6.x. Miej na uwadze, źe w przypadku kompilacji jądra serii 2.4 występują subtelne róźnice!
Przebieg kompilacji i instalacji jądra moźemy bardzo ogólnie opisać w paru punktach:
* Zdobycie żródeł, oraz informacji o sprzęcie
* Konfiguracja -> od zera, lub z wykorzystaniem istniejącej konfiguracji
* Kompilacja
o Obrazu jądra
o Modułów
* Instalacja (kolejność nie ma znaczenia)
o Modułów
o Skopiowanie lub przeniesienie obrazu jądra do /boot
o Wygenerowanie ramdysku initrd i umieszczenie go w /boot (opcjonalnie -> w przypadku gdy główny system plików, którego obsługa jest niezbędna do załadowania systemu nie został wkompilowany na stałe w jądro, lub w przypadku korzystania z duetu bufora ramki (frame buffer, pozwalający na osiągnięcie wysokiej rozdzielczości w konsoli, a takźe 32 bitowej palety kolorów, co pozwala m.in. oglądać filmy w czystej konsoli (po uprzednim ustawieniu wyjscia video w naszym ulubionym odtwarzaczu na bufor ramki)) i tzw. bootsplash'a, czyli grafiki/animacji wyświetlanej podczas uruchamiania systemu)
* Konfiguracja bootloadera (dodanie nowych wpisów dla nowego kernela)
* Reboot i pacierz ;)
Pierwszym krokiem jest zaopatrzenie się w żródła jądra. Archiwa 'waniliowego' (czyli gołego, bez dodatkowych patchsetów dostępnych w dystrybucyjnych Linuksach) kernela moźemy pobrać ze strony
http://www.kernel.org. Naukę kompilacji najlepiej przeprowadzać pod Slackware, poniewaź nie korzysta on z źadnych patchsetów, co pozwoli nam na uniknięcie przykrych niespodzianek typu „Po kompilacji jądra nie działa mi skaner” (bo jego sterownik dostępny był w postaci patcha lub wchodził w skład patchsetu). Jeśli juź musimy kompilować jądra np. pod Mandrivą, Fedorą czy Ubuntu zalecam aby zaopatrzyć się w pakiet ze żródłami jądra pochodzący z repozytorium. W ten sposób otrzymamy kompletne, połatane żródła Linuksa.
Żródła „jajka” najczęściej umieszcza się w
/usr/src. Po wypakowaniu archiwum naszym oczom ukaźe się
katalog linux-wersja. Warto utworzyć sobie dowiązanie symboliczne
/usr/src/linux prowadzące do żródeł naszego jądra.
Niektóre programy podczas kompilacji wymagają dostępu do żródeł jądra. Przykładem mogą być sterowniki dostarczane w postaci kodu żródłowego, z którego budowany jest moduł jądra. Jeśli w systemie mamy kilka kerneli, moźe pojawić się pytanie -> skąd wiadomo w którym katalogu szukać żródeł jądra? Modyfikacja dowiązania /usr/src/linux przy kaźdym uruchomieniu systemu na danym jądrze jest rozwiązaniem bardzo nieeleganckim, poszukiwanie żródeł w /usr/src/ z wykorzystaniem
uname -r takźe nie jest zbyt szczęśliwym wyjściem z sytuacji bo te niekoniecznie muszą się znajdować akurat tam. Dlatego istnieją inne dowiązania - np.
/lib/modules/`uname -r`/source
Sam
katalog /lib/modules
jak sama nazwa wskazuje jest miejscem, w którym przechowywane są skompilowane moduły jądra, w kaźdej chwili gotowe do załadowania.
Jeśli chodzi o informacje na temat sprzętu -> podstawowe informacje moźemy otrzymać poprzez wykorzystanie poleceń:
Kod
Czym są moduły?
Większość ficzerów moźemy zbudować w postaci modułu, zamiast integrować z samym jądrem (co ma wpływ na wielkość jego obrazu). Główną zaletą modułów jest moźliwość ich ładowania i usuwania z pamięci, czyli poszerzanie/zwęźanie moźliwości naszego Linuksa i to bez potrzeby ponownego uruchamiania systemu (Co ma niebagatelne znaczenie np. w przypadku serwerów)! Ficzery z których korzystamy rzadko, a są pamięcioźerne (np. obsługa systemów plików -> jeśli nie uźywamy danego systemu plików na danej maszynie, lub rzadko zachodzi taka potrzeba) warto kompilować do postaci modułu (załóźmy, źe zdarza się, iź raz na miesiąc musimy coś przekopiować z cudzego dysku na którym wykorzystuje się inny system plików. Trzymanie w pamięci funkcji odpowiedzialnych za jego obsługę jest marnotrawieniem czasu, podobnie jak kompilacja osobnego jądra wyposaźonego w daną funkcjonalność. W takim przypadku mamy moźliwość załadowania modułu na czas wykonania odpowiednich zadań i póżniejsze ich wyłączenie, bez ponownego startu systemu).
Ogromne pole do popisu dają tzw.
SoftLevele, dostępne m.in. w Gentoo, które pozwalają tworzyć osobne profile skryptów startowych, w zaleźności od parametru podanego w bootloaderze. Co to oznacza w praktyce? Jeśli np. w domu korzystamy z połączenia kablowego, natomiast na uczelni przesiadamy się na sieć bezprzewodową, to moźemy z poziomu bootloadera zadecydować m.in. które skrypty startowe zostaną załadowane (moźemy stworzyć 2 skrypty startowe, z czego 1 odpowiada za załadowanie modułów do obsługi karty wlan oraz podniesienie odpowiednich interfejsów, a drugi dotyczy tradycyjnej karty sieciowej). I nie marnujemy czasu na kompilację 2 linuksów, tym samym oszczędzając wolną pamięć.
Kwestia konfiguracji -> tysiące przeróźnych HOWTO's i Artykułów powstało na ten temat. Najlepszą metodą na opanowanie tej sztuki jest eksperymentowanie i samodzielne próby. Dobrą techniką jest uźycie konfiguracji wykorzystywanej w jądrze dystrybucyjnym i jego modyfikacja pod kątem własnych potrzeb. Jeśli jądro zostało skompilowane z obsługą
IKCONFIG_PROC (
„General Setup” -> „Enable access to .config through /proc/config.gz”, wymaga uwcześniejszego zaznaczenia opcji „
Kernel .config support” znajdujuącego się w tym samym podmenu) moźemy wyświetlić config kernela przy pomocy polecenia
Kod W przeciwnym wypadku kopia pliku konfiguracyjnego powinna znajdować się
w katalogu /boot.
Moja rada: Początkujący powienien trzymać się zasady, źe jeśli nie jest pewien jakiejś opcji to powinien jej nie ruszać.
Konfiguracja jądra zawiera się w 1 pliku tekstowym
.config (kropka na początku nazwy), znajdującym się w katalogu żródeł. Jego modyfikacji, czyli „skrajania kernela na miarę”, moźemy dokonywac na kilka sposobów:
# Edycję pliku przy pomocy ulubionego edytora tekstowego, jednak jest to rozwiązanie dla masochistów lub ludzi którzy wiedzą co chcą zmienić i w ich przypadku uźywanie dodatkowych narzędzi byłoby stratą czasu.
# Uźycie jednego z kilku dostępnych narzędzi (wywołujemy poprzez polecenie make nazwa_narzędzia):
* menuconfig -> tekstowy edytor wykorzystujący bibliotekę ncurses. W tym przypadku
symbol gwiazdki ('*') oznacza 'wkompilowane w jądro', duźa litera
'M' oznacza moduł, natomiast
puste pole to wyłączenie danej funkcji z jądra. Jeśli
'*'/'M'/' ' jest otoczone ostrymi nawiasami -> osnacza to, iź dana opcja moźe zostać wkompilowana w jądro na stałe, jako moduł, lub wcale.
Nawias indeksowy oznacza, źe dana opcja nie moźe pojawić się w postaci modułu. Przykładem moźe być obsługa modułów. Myśliki oznaczają brak moźliwości zmiany statusu. Strzałka za nazwą oznacza, iź opcja posiada podmenu.
Podsumowując - jest to najlepsze narzedzie, ze względu na przejrzystość interfejsu oraz niewielkie zaleźności software'owe.
* xconfig, gconfig -> graficzne narzędzie do konfiguracji jądra, których filozofia i obsługa jest analogiczna do menuconfig. Ich wadą jsą zaleźności -> poza systemem Xwindow (X.Org/XFree86[starsza wersja]) wymagane są takźe odpowiednie biblioteki, np. Qt, czy GTK. Niewątpliwą zaletą tych 2 rozwiązań jest przejrzystość.
* oldconfig -> po wcześniejszym skopiowaniu pliku konfiguracyjnego pochodzącego ze starszego lub nowszego jądra w katalogu ze żródłami, narzędzie to uaktualnia jego zawartość (jeśli w skopiowanym .config'u któraś z opcji się nie pojawiła, dopisuje ją i ustawia jej domyślny atrybut)
* defconfig -> tworzy nowy .config uźywając domyślnych ustawień.
Więcej aktualnych informacji moźna uzyskać poprzez komendę
Kod wywołaną w katalogu ze żródłami jądra.
Wskazówka z mojej strony: [color=red]Takie rzeczy jak obsługa kontrolera dysków, czy systemu plików znajdującego się na głównej partycji zawsze warto integrować z jądrem[/color]. Są to rzeczy z których korzystać będziemy zawsze, więc zbudowanie ich w postaci modułów nie przyniesie nam źadnych korzyści (chyba źe jest się deweloperem jakiejś dystrybucji odpowiedzialnym za sam kernel i chce się zapewnić uniwersalność, połączoną z moźliwościa wyłączenia niepotrzebnych sterowników [z tym, źe jeśli ktoś się chwyta za takie rzeczy to posiada odpowiednią wiedzę i nie trzeba go pouczać]). W przeciwnym wypadku musimy pamiętać nie tylko o
wygenerowaniu initrd, ale takźe o włączeniu odpowiedniej opcji w jądrze, która umoźliwia zastosowanie tego rozwiązania.
Dlaczego?
Jak juź wcześniej wspominałem -> moduły znajdują się na dysku twardym, w katalogu
/lib/modules/wersja_jądra/. Aby się do nich dostać wymagana jest obsługa kontrolera i systemu plików. Nie jesteśmy w stanie wczytac sterownika, które zapewnia obsługę danego urządzenia, jeśli znajduje się na tym urządzeniu (
tutaj goraco pozdrawiam producentów napedów blu-ray, którzy sterowniki umieszczają na krąźkach blue-ray ;) ).
Aby ominąć ten problem, naleźy umieścić sterownik w ram dysku (initrd).
Przejdżmy do kolejnego kroku -> czyli właściwej kompilacji. Moźemy kompilowac na dwa sposoby:
o Uźywając jednego polecenia: Kod lub
Kod (bo
domyślnym targetem dla make
jest '
all'), które:
1) skompiluje jądro (make vmlinux),
2) utworzy jego skompresowany obraz (make bzImage),
3) zbuduje moduły (make modules).
o Uźywając 2 poniźszych poleceń, etap po etapie, zachowując przy tym większą kontrolę nad całym procesem kompilacji oraz umoźliwiając łatwe zdiagnozowanie której części procesu kompilacji dotyczy ew. błąd.
Kod (bzImage wyzwala vmlinux -> wystarczy zajrzeć do Makefile znajdującego się w podkatalogu
arch/`uname -m`/)
Kod
Teraz przechodzimy do instalacji nowego jądra.
Tutaj moźemy równieź skorzystać z jednego polecenia, lub wykonać cały zabieg ręcznie:
1) Metoda automatyczna
Kod -> to polecenie skopiuje obraz jądra do
/boot, doda odpowiedni wpisy do
bootloadera. Podczas instalacji wykorzystywany jest skrypt
~/bin/installkernel,
/sbin/installkernel lub jądro jest instalowane w
$(INSTALL_PATH) i automatycznie uruchamiany jest wyzwalacz dla bootloadera
LILO (dodanie wpsiu z nowym jądrem).
2) Metoda ręczna
Moduły instalujemy następującym poleceniem:
Kod
Natomiast obraz jądra kopiujemy do boot
Kod cp arch/`uname -m`/boot/bzImage /boot/jajko-wersja
Musimy tutaj pamiętać o ręcznym dodaniu wpisów do
bootloadera. Jeśli korzystamy z
LILO, modyfikujemy plik
/etc/lilo.conf, zachowując składnię przedstawioną poniźej:
Kod image=/boot/nazwa_obrazu opcje #sciezka do obrazu jadram oraz ew. opcje
(dla jądra, dla framebuffera, czy def. softlevelu)
label=nowe_jajko #label czyli tresc etykiety w menu LILO
initrd=/boot/initrd-2.2.12-20.img #opcjonalnie
read-only
root=/dev/sda1 #tutaj podajemy partycję główną
W przypadku
GRUB'a edytujemy jeden z plików:
/etc/grub.conf,
/boot/grub/menu.lst lub
/boot/grub/grub.conf, wg schematu:
Kod title nowe_jajko
root (hd0,0)
kernel sciezka_do_obrazu_jadra opcje
initrd sciezka_do_initrd
Jeśli istnieje taka potrzeba -> naleźy jeszcze utworzyć
plik initrd, np.
przy pomocy narzędzia mkinitrd
Po kazdej rekompilacji jądra (a dokładnie -> przebudowie modułów) naleźy pamiętać iź
sterowniki dostarczane w postaci zewnętrznych modułów, jak np. nvidia-drivers, wymagają reinstalacji!
Hwastu