MindShifter - nFire.eu   MindShifter - nFire.eu
  [ Zaloguj | Rejestracja ]     Dzisiaj jest : Piątek, 22 Czerwiec 2018 
Menu strony
 
Artykuły

Wszystkie artykuły » Linux » Podstawy » Kompilacja kernela (kernel 2.6)

Kompilacja kernela (kernel 2.6)

Autor: Dariusz Jaskuła (MindShifter) | Sobota, 23 Październik 2010 16:05


kompilacjaPrzedstawię w jaki sposób kompiluje się kernel na przykładzie systemu Debian GNU/Linux.

Metoda ta prowadzi do utworzenia pakietów (.deb). Pakiety mają oczywistą przewagę nad tradycyjną metodą kompilacji. W tradycyjnej metodzie kompilujemy źródła i instalujemy je na tej samej maszynie. Pakiety dają nam możliwość przeniesienia ich na dowolną maszynę, gdzie je po prostu instalujemy jak każdy inny pakiet (oczywiście maszyna ta musi być zgodną z architekturą dla jakiej kompilowaliśmy kernel).

Jeśli musimy zaktualizować kernel na wielu maszynach o tej samej architekturze jest to rozwiązanie idealne. Tylko jedna z maszyn musi mieć zainstalowany pakiet służący do kompilacji źródeł kernela i tylko na niej wymagana jest znacznie większa wolna przestrzeń niezbędna do kompilacji.



Wstęp

Zanim zaczniemy zapoznamy się ze sposobem numeracji wersji kernela (jądra) linuksa. Wersje kernela składają się z numerów rozdzielonych kropką w postaci: A.B.C.D:
  • A - wskazuje na główny numer wersji, obecnie jest to 2.
  • B - wskazuje na numer podwersji, obecnie jest to 6. Przyjęto, że parzyste numery podwersji nadawane są stabilnym wersjom jądra a numery nieparzyste wersjom rozwojowym.
  • C - wskazuje na numer poprawki.
  • D - wskazuje na numer drobnej poprawki.
np. 2.6.14.3 wskazuje na stabilną wersję jądra 2.6 z poprawką 14.3.

Kernela nie trzeba za każdym razem kompilować od początku. Jeśli posiadamy źródła poprzedniej wersji możemy nałożyć na nią łatę (patch). Łaty są plikiem tekstowym zawierającym zmiany jakie zaszły między kolejnymi wersjami kernela - są więc zdecydowanie mniejsze niż całe źródło a proces łatania jest szybszy niż kompilacja kernela od zera.

Zasada nakładania łat jest następująca:
  • patch-2.6.20 nakłada się na źródło kernela 2.6.19
  • patch-2.6.19.7 nakłada się na źródło kernala 2.6.19 (przy nakładaniu na 2.6.19.x mogą pojawić się błędy).
Łaty podobnie jak i sam kernel dostępne są na www.kernel.org.

I jeszcze parę słów o samym kernelu. Zawarty jest on w katalogu /boot w pliku vmlinuz-A.B.C.D-przyrostek ("vm" oznacza obsługę pamięci wirtualnej a "z" kompresję kernela). A.B.C.D to oczywiście wersja kernela a przyrostek pozwala rozróżniać różne konfiguracje kernela. Nazwa tego pliku może być oczywiście dowolna, lecz taki sposób nazewnictwa jednoznacznie określa wersję kernela.

Naszym celem będzie instalacja jądra 2.6.35.7 na maszynie z jądrem:
$ uname -r
2.6.26-2-686
Jest to Debian lenny a więc stosunkowo stara dystrybucja.

Przygotowanie systemu

Na początek sprawdzamy źródła pakietów. Jeśli nie mamy w nich wpisów backports i ftp.pl.debian.org to proponuję je dodać edytując plik /etc/apt/sources.list:
deb http://ftp.pl.debian.org/debian/ lenny main non-free contrib
deb-src http://ftp.pl.debian.org/debian/ lenny main non-free contrib
deb http://www.backports.org/debian lenny-backports main contrib non-free
deb-src http://www.backports.org/debian lenny-backports main contrib non-free
po zmianach w /etc/apt/sources.list aktualizujemy apta:
# apt-get update
# aptitude update
Instalujemy niezbędne składniki do kompilacji kernela:
# aptitude install build-essential
# aptitude install kernel-package
# aptitude install libncurses5-dev
Ostatni pakiet jest niezbędny do kompilacji menuconfig (program do konfiguracji kernela).

Teraz sprawdzamy wersję kernel-package:
# aptitude show kernel-package

Pakiet: kernel-package
Nowy: tak
Stan: zainstalowany
Zainstalowany automatycznie: nie
Wersja 11.015
(...)
Jest to najnowsza wersja dla naszego systemu (Debian lenny) jednak kompilacja docelowego kernela nie powiedzie się, gdyż będziemy potrzebować wersji z nowszej dystrybucji (12.036).

Przechodzimy na stronę packages.debian.org do sekcji "Przeszukiwanie katalogów z pakietami" i szukamy pakietu kernel-package (musimy jeszcze zmienić pole "Dystrybucja" na dowolna - pakiet znajduje się obecnie w wersji testowej).

Odnajdujemy w ten sposób pakiet squeeze (testing) (kernel): Narzędzie do budowania pakietów Debiana związanych z jądrem Linuksa 12.036: all.

Idąc na skróty ściągamy i instalujemy ten pakiet:
# wget http://ftp.pl.debian.org/debian/pool/main/k/kernel-package/kernel-package_12.036_all.deb
# dpkg -i kernel-package_12.036_all.deb
Pakiet kernel-package powinien zostać prawidłowo zaktualizowany do nowszej wersji:
# aptitude show kernel-package

Pakiet: kernel-package
Nowy: tak
Stan: zainstalowany
Zainstalowany automatycznie: nie
Wersja 12.036
(...)

Rozpoznanie systemu

Przed kompilacją warto dokładnie zapoznać się z posiadaną platformą sprzętową. W katalogu /proc zamontowany jest system plików procfs. Jest on dynamicznym interfejsem kernela przechowującym wiele przydatnych informacje m.in. o sprzęcie. Dla przykładu aby dowiedzieć się jaki posiadamy procesor wydajemy polecenie:
# cat /proc/cpuinfo
Jeśli interesują nas informacje o urządzeniach PCI wydajemy polecenie:
# lspci
Informacje o urządzeniach podłączonych do portu USB uzyskamy wydając polecenie:
# lsusb

Pobranie źródeł kernela

Mając przygotowane środowisko i znając dokładnie platformę możemy przystąpić do kompilacji i instalacji nowego kernela.

Najnowszy kernel znajdziemy zawsze na stronie www.kernel.org. Pod adresem www.kernel.org/pub/linux/kernel/v2.6/ znajduje się plik o nazwie LATEST-IS-2.6.x wskazujący na najnowszą wersję kernela. Przyjęło się, że źródła umieszcza się w katalogu /usr/src/ w nim więc dokonamy naszej kompilacji. Ściągamy źródła kernela i wypakowujemy:
# cd /usr/src
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.35.7.tar.bz2
# tar xvf linux-2.6.35.7.tar.bz2
Plik ten ma rozmiar ok. 67 MB. Do wypakowania wymaga ok. 460 MB wolnej przestrzeni:
# du -sh linux-2.6.35.7
458M	linux-2.6.35.7
Po kompilacji katalog ten zajmować będzie prawie 1 GB!

Dobrym zwyczajem jest utworzenie dowiązania symboliczngo o nazwie "linux" wskazującego na najnowszą wersję kernela:
# ln -s linux-2.6.35.7 linux

Patchowanie (łatanie) kernela

Jeśli chcemy nałożyć łatę na kernel to wykonujemy to właśnie w tym miejscu (nie dotyczy to naszego przypadku). Dla przykładu mając kernel 2.6.34 możemy go spatchować do 2.6.35 poprzez:
# cd /usr/src
# wget http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.35.bz2
# cd /usr/src/linux-2.6.34

# bzip2 -dc /usr/src/patch-2.6.35.bz2 | patch -p1 --dry-run
# bzip2 -dc /usr/src/patch-2.6.35.bz2 | patch -p1
Pierwsze polecenie patch (z parametrem --dry-run) jedynie symuluje nakładanie łaty - jeśli nie wyrzuci błędów można przeprowadzić łatanie drugim poleceniem patch.

Konfiguracja kernela

Wracamy do naszej kompilacji. Na początek czyścimy źródło:
# cd /usr/src/linux
# make clean && make mrproper
Przystępujemy do konfiguracji kernela. Możemy do tego wykorzystać nasze stare ustawienia z poprzedniej konfiguracji kernela. Ustawienia te powinny znajdować się w katalogu boot w pliku o nazwie config-WERSJAKERNELA:
# cp /boot/config-`uname -r` ./.config
Kompilujemy menu konfiguracji kernela:
# make menuconfig
Linux Kernel Configuration

Jeśli skopiowaliśmy poprzednie ustawienia to zostaną one automatycznie załadowane z pliku .config (ustawienia możemy także załadować wybierając "Load an Alternate Configuration File").

Warto zwrócić uwagę czy w ustawieniach: Procesor type and features -> Procesor family wybrana jest właściwa dla naszej maszyny rodzina procesorów. Pozwoli to maksymalnie zoptymalizować nasz nowy kernel do naszej platformy.

Kernel musi mieć odpowiednie sterowniki do naszego dysku, np. dla dysków SCSI będzie to gałąź: Device drivers -> SCSI device support.

Musimy także zadbać o obsługę systemu plików. Obsługiwane systemy plików znajdują się w gałęzi: File systems.

Dla ustawień tych możemy wybrać opcję modułu, konieczne będzie wtedy skorzystanie z ramdysku przy starcie systemu (będzie o tym niżej).

Generalnie należy dążyć do modularyzacji kernela - starać się jak największą liczbę funkcji skompilować jako moduł a nie jako stały składnik kernela (wkompilowany w kernel). Wyłączenie funkcji z jądra i wprowadzenie jej poprzez moduł powoduje, że jądro będzie mniejsze i bardziej elastyczne. Moduł w razie konieczności zawsze można załadować do jądra a gdy nie jest potrzebny po prostu usunąć z pamięci. Moduły przechowywane są w katalogu /lib/modules/wersja_kernela/.

Po dokonaniu zmian zapisujemy konfigurację i opuszczamy menuconfig wybierając Save an Alternate Configuration File (zapisujemy jako .config).

Kompilacja kernela

Uwaga !
Źródła tego kernela nie skompilują się z powodu brakującego pliku nagłówka eventfd.h w pliku lguest.c. Okazuje się jednak, że nie jest on potrzebny do kompilacji. Wystarczy zakomentować #include <sys/eventfd.h> w pliku Documentation/lguest/lguest.c bez konieczności instalacji dodatkowych plików nagłówkowych.


Przystępujemy do kompilacji kernela, która może sporo potrwać (trzeba liczyć ok. 2h). Przez opcję --append-to-version możemy dołączyć przyrostek (tu "-mykernel") identyfikujący różne konfiguracje kernela:
# make-kpkg clean
# make-kpkg --initrd --append-to-version=-mykernel kernel_image kernel_headers
Jeśli kompilacja nie powiedzie się przyglądamy się błędom i próbujemy je naprawić (google). Częstym powodem jest nieprawidłowa konfiguracja kernela - powtarzamy wówczas proces konfiguracji kernela (make menuconfig) i ponawiamy kompilację kernela.

Instalacja kernela

Jeśli kompilacja zakończyła się powodzeniem to w katalogu /usr/src zostaną utworzone dwie paczki z obrazem kernela i nagłówkami. Instalujemy je:
# cd ..
# dpkg -i linux-image-2.6.35.7-mykernel_2.6.35.7-mykernel-10.00.Custom_i386.deb
# dpkg -i linux-headers-2.6.35.7-mykernel_2.6.35.7-mykernel-10.00.Custom_i386.deb
Jeśli używamy programu rozruchowego GRUB to instalator automatycznie wprowadzi odpowiednie zmiany (do pliku /boot/grub/menu.lst). W katalogu /boot powinny zostać utworzone pliki:
  • config-2.6.35.7-mykernel (konfiguracja kernela).
  • vmlinuz-2.6.35.7-mykernel (skompresowany plik kernela).
  • System.map-2.6.35.7-mykernel (plik zawiera adresy i nazwy funkcji oraz zmiennych z pliku binarnego kernela - przydatne przy debugowaniu).
I to już koniec. Pozostaje uruchomić ponownie maszynę i przy starcie wybrać już nowy kernel.
# shutdown -r now
GRUB

Ramdysk

Nadgorliwość w dążeniu do modularyzacji kernela może doprowadzić do pojawienia się błędu sktutkującego niemożliwością załadowania systemu.

Jeśli po zmianie kernela system przywita nas komunikatem:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Kernel panic

nie należy, tak jak kernel, panikować tylko zrestartować system i wybrać stary kernel.

Powodem tego błędu jest brak wkompilowanej w kernel obsługi naszego dysku i/lub systemu plików (jeśli podczas konfiguracji obsługa ta została załączona jako moduł).

Aby odczytać nasz dysk kernel musi załadować (jako moduł) sterowniki. Problem polega na tym, że sterowniki te znajdują się w /lib/modules/ i aby je odczytać kernel musi mieć sterowniki do tego dysku. Powstaje więc błędne koło - mamy sterownik do dysku ale aby je odczytać i załadować musimy mieć sterownik do tego dysku.

Sytuacja bez wyjścia? Na szczęście nie do końca.

Problem ten można obejść na dwa sposoby: obsługę dysku i systemu plików można wkompilować w jądro lub pozostawić je zmodularyzowane i skorzystać z ramdysku.

Ramdysk podobnie jak kernel może być załadowany przez bootloader. W ramdysku znajdują się odpowiednie moduły. Moduły z ramdysku zostają załadowane do pamięci i kernel ma do nich dostęp.

Aby utworzyć ramdysk wydajemy polecenie:
# mkinitramfs -o /boot/initrd.img-2.6.35.7-mykernel /lib/modules/2.6.35.7-mykernel/
(jeśli nie dysponujemy programem mkinitramfs to instalujemy go przez: aptitude install initramfs-tools).

Teraz należy jeszcze dodać odpowideni wpis ramdysku (initrd) do GRUB-a (/boot/grub/menu.lst):
title	Debian GNU/Linux, kernel 2.6.35.7-mykernel
root	(hd0,0)
kernel	/boot/vmlinuz-2.6.35.7-mykernel root=/dev/sda1 ro quiet
initrd	/boot/initrd.img-2.6.35.7-mykernel

title	Debian GNU/Linux, kernel 2.6.35.7-mykernel (single-user mode)
root	(hd0,0)
kernel	/boot/vmlinuz-2.6.35.7-mykernel root=/dev/sda1 ro single
initrd	/boot/initrd.img-2.6.35.7-mykernel
Zmiany w menu.lst nie wymagają dodatkowych działań na bootloaderze. Można zrestartować system:
# shutdown -r now
Tym razem kernel powinien się załadować.

Zakończenie

Po zmianie kernela musimy zainstalować kluczowe pakiety bezpośrednio zależne od kernela - dla przykładu konieczna będzie instalacja sterowników dla karty NVIDIA:
# wget http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/NVIDIA-Linux-x86-260.19.12.run
# chmod +x NVIDIA-Linux-x86-260.19.12.run 
# sh NVIDIA-Linux-x86-260.19.12.run 
# shutdown -r now
Na zakończenie podsumuję proces kompilacji kernela podając dla odmiany metodę ogólną, którą kompiluje się kernel na dowolnym systemie linux bez tworzenia pakietów:
# make clean && make mrproper
# make menuconfig
# make
# make modules_install
# make install
Ostatnie polecenie kopiuje plik kernela (arch/i386/boot/bzImage) oraz System.map w odpowiednie miejsce i próbuje uaktualnić bootloader. Jeśli z jakiegoś powodu mu się to nie uda należy to zrobić ręcznie - dla LILO będzie to plik /etc/lilo.conf dla GRUB-a /boot/grub/menu.lst. W przypadku LILO należy pamiętać o wydaniu polecenia lilo po zmianach w menu bootloadera.

   [ Drukuj ] [ Wyślij stronę ]

Komentarze

Dodaj komentarz!


Wszystkie obrazy, grafika, tekst oraz wszelkie inne treści reprezentowana na tej stronie (oprócz niektórych z działu Download) są chronione prawami autorskimi i są wyłączną własnością autora tej strony. Wszelkie przypadki użycia i/lub publikacji są zastrzeżone na całym świecie. Wszystkie zdjęcia i inne treści są wyraźnie nie w Domenie Publicznej. Żadne zdjęcia ani inne materiały na tej stronie nie mogą być kopiowana, przechowywana, poddawane manipulacji, publikowane, sprzedawane lub cytowane w całości lub w części w jakiejkolwiek formie bez uprzedniej pisemnej zgody upoważnionego przedstawiciela tej strony.

Jako materiał chroniony prawami autorskimi, wszystkie zdjęcia umieszczone na tej stronie chronione są zgodnie z międzynarodowym prawem autorskim.

All images, graphics, text, and all other content represented on this website (except for some of the Download section) are copyrighted and are the sole property of author of this website. All use and/or publication rights are reserved worldwide. All images and all other content are expressly not in the Public Domain. No images or other content on this website may be copied, stored, manipulated, published, sold or reproduced in whole or in part in any form without the prior written authorization of an authorized representative.

As copyrighted material, all images displayed on this site are protected under international copyright laws.

....:::: © 2004-2009 MindShifter ]:::::[ kontakt: Gadu-Gadu 2644644 ::::....