Principalul motiv pentru care se dorește compilarea kernel-ului este adaptarea acestuia la un anumit sistem cu scopul creșterii performanțelor, adaptare care de obicei constă în:
În cazul kernel-ului Linux, suportul pentru hardware/software poate să fie:
Deși adăugarea funcționalităților în kernel poate duce la creșterea eficienței în anumite subsisteme, acest lucru poate avea ca și consecință îngreunarea sistemului în ansamblu (bloated), lucru nerecomandat.
Majoritatea distribuțiilor includ în kernel numai suportul pentru componentele critice, fără de care sistemul de operare nu poate funcționa. Restul componentelor sunt compilate sub forma de module, module care sunt încărcate în funcție de hardware-ul/necesitățile fiecărui sistem/utilizator.
Există și situații în care kernel-ul care vine cu o anumită distribuție este mai vechi sau nu are compilat suportul pentru o anumită componentă. De asemenea, compilarea unui kernel optimizat este des întalnită pe sistemele care ruleaza server-e unde se dorește exploatarea la maxim a resurselor sistemului.
Pentru a putea efectua modificări de tipul celor mentionate mai sus, trebuie inițial efectuată configurarea kernel-ului. După această etapă se poate porni compilarea kernel-ului și a modulelor de kernel.
Înaintea compilării kernel-ului trebuie verificat dacă sistemul satisface cerințele hardware și software.
Din punct de vedere hardware:
Timpul de compilare variază în funcție de numărul de componente activate pentru compilare în momentul configurării.
Compilarea se poate realiza pe un sistem mai puternic urmând ca apoi să se mute pachetul ce conține kernel-ul pe sistemul destinație.
Cerințele software pentru kernel-ul de compilat se găsesc precizate în fișierul Documentation/Changes din cadrul surselor:
o Gnu C 3.2 # gcc --version o Gnu make 3.79.1 # make --version o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version o module-init-tools 0.9.10 # depmod -V o e2fsprogs 1.29 # tune2fs o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs o xfsprogs 2.6.0 # xfs_db -V o pcmciautils 004 # pccardctl -V o quota-tools 3.09 # quota -V o PPP 2.4.0 # pppd --version o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version o nfs-utils 1.0.5 # showmount --version o procps 3.2.0 # ps --version o oprofile 0.9 # oprofiled --version o udev 081 # udevinfo -V o grub 0.93 # grub --version
Observații:
e2fsprogs
, jfsutils
, reiserfsprogs
, xfsprogs
sunt folosite pentru sistemul de fișiere asociatPPP
și isdn4k-utils
sunt necesare numai dacă legăturile sistemului la Internet sunt de tip PPP sau ISDN.
Un kernel compilat poate oferi suport doar pentru hardware-ul utilizatorului, micșorând astfel dimensiunea imaginii obținute. De asemenea, cunoașterea hardware-ului în sistem este necesară pentru un kernel mai rapid și alegerea opțiunilor de compilare și a driver-elor de dispozitiv corecte.
Informații despre controller-ele Ethernet, VGA, placa de sunet se află cu ajutorul comenzii lspci
(din pachetul pciutils
):
# lspci 00:00.0 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:00.1 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:00.2 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:00.3 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:00.4 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:00.7 Host bridge: VIA Technologies, Inc. K8M800 Host Bridge 00:01.0 PCI bridge: VIA Technologies, Inc. VT8237 PCI bridge [K8T800/K8T890 South] 00:0a.0 Ethernet controller: Linksys, A Division of Cisco Systems [AirConn] ...
Tipul procesorului se află cu ajutorul procfs
(montat în /proc
).
# cat /proc/cpuinfo processor : 0 vendor_id : AuthenticAMD cpu family : 15 model : 28 model name : Mobile AMD Sempron(tm) Processor 2800+ stepping : 0 cpu MHz : 1601.122 cache size : 256 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 1 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr ... bogomips : 3205.53
Sursele de kernel de Linux pot fi obținute din pachete specifice distribuției sau pot fi descărcate sursele oficiale ale lui Linus Torvalds.
În cazul în care se alege varianta folosirii surselor oficiale, se recomandă folosirea unui mirror din Romania.
Sursele kernel-ului se găsesc în subdirectorul /pub/linux/kernel/v2.6
(pentru versiunea 2.6). Se poate folosi http sau ftp pentru obținerea surselor:
# cd /usr/src # wget ftp://ftp.idilis.lkams.kernel.org/pub/linux/kernel/v2.6/linux-2.6.24.2.tar.gz
Se dezarhivează sursele. Se recomandă crearea unei legături simbolice cu numele linux
către directorul ce contine sursele.
# cd /usr/src # tar xzf linux-2.6.24.2.tar.gz # ln -s linux-2.6.24.2 linux # ls -l total 40924 lrwxrwxrwx 1 root src 14 2008-02-19 13:52 linux -> linux-2.6.24.2 drwxrwxrwx 19 root root 4096 2008-02-16 19:21 linux-2.6.24.2 -rw-r--r-- 1 root src 41853865 2008-02-16 19:28 linux-2.6.24.2.tar.gz
Kernel-ul compilat de pe mașina virtuală de Linux disponibilă este un kernel versiunea 2.6.31.6.
Partea de configurare este partea cea mai importantă a procesului de compilare. În cadrul acesteia se decide ce caracteristici vor fi incluse în noul kernel; sunt necesare cunoștințe ale hardware-ului sistemului și ale facilităților dorite.
Procesul de configurare era unul destul de dificil de realizat la primele versiuni, însa acest lucru s-a schimbat odată cu introducerea unor interfețe care folosesc X Window sau ncurses. Pentru verificarea opțiunilor posibile de compilare se poate rula comanda:
# make help Cleaning targets: clean - remove most generated files but keep the config mrproper - remove all generated files + config + various backup files Configuration targets: config - Update current config utilising a line-oriented program menuconfig - Update current config utilising a menu based program xconfig - Update current config utilising a QT based front-end gconfig - Update current config utilising a GTK based front-end oldconfig - Update current config utilising a provided .config as base randconfig - New config with random answer to all options defconfig - New config with default answer to all options allmodconfig - New config selecting modules when possible allyesconfig - New config where all options are accepted with yes allnoconfig - New config where all options are answered with no ...
Pentru utilizarea unei interfețe text-based (ncurses), va trebui instalat pachetul libncurses-dev
. Pentru utilizarea unei interfețe folosind front-end GTK (de obicei într-un desktop environment GNOME) vor trebui instalate pachetele libgtk2.0-dev
și libglade2.0-dev
. Pentru QT va trebui instalat pachetul libqt4-dev
.
Avantajul folosirii interfetei ncurses este faptul că este relativ ușor de utilizat și nu necesită prezenta unui mediu grafic.
În cazul în care sursele conțineau o configurație anterioară care nu mai este dorită, va trebui rulată una dintre comenzile:
# make clean # make mrproper
Rularea uneia dintre comenzile:
# make menuconfig # make gconfig # make xconfig
rezultă în afișarea unui meniu. Acesta conține mai multe intrări de configurare (General setup
, Networking
, Device drivers
, File systems
, etc.) care pot fi utilizate pentru configurări ale unui subdomeniu. Acestea pot conține, la rândul lor, alte subdomenii de configurare.
O opțiune finită de configurare (spre exemplu Device Drivers → Block Devices → Normal floppy disk support
) poate prezenta utilizatorului trei optiuni de configurare:
<N>
)<Y>
)<M>
)
Compilarea built-in înseamnă introducerea codului obiect asociat opțiunii în imaginea de kernel care va rezulta. Compilarea în forma de modul de kernel înseamnă că pentru activarea acelei facilități, kernel-ul va încărca modulul (codul obiect asociat) și îl va descărca atunci când nu are nevoie de el. Kernel-ul este astfel extensibil și pentru adăugarea anumitor facilități nu este nevoie de recompilare. Pentru lucrul cu module de kernel vor trebui adăugate opțiunile din Loadable module support (Enable loadable module support
).
Multe opțiuni nu vor fi încorporate în cadrul kernel-ului întrucât nu sunt necesare. Altele pot fi compilate numai built-in. Opțiunile care suportă varianta modul de kernel sau built-in se recomandă a fi compilate ca module de kernel pentru a fi încărcate la nevoie. Pe procesoarele moderne, timpul în care se încarcă/descarcă module este suficient de mic încat compilarea ca modul de kernel sau built-in să nu afecteze performanța.
O opțiune utilă este precizarea unei versiuni locale pentru kernel, astfel încât acesta să fie identificat; exista posibilitatea compilării aceleiași versiuni de kernel pentru scopuri distincte; oferirea unei versiuni locale generează o versiune de kernel unică.
Precizarea tipului de procesor și a arhitecturii este un pas necesar pentru a crea un kernel eficient. Majoritatea opțiunilor țin de preferințele utilizatorilor (desi probabil multi vor alege suport de networking, sunet etc.) sau de hardware-ul existent.
Dacă se dorește crearea unui kernel pentru dezvoltare (development) atunci vor trebui activate opțiunile din Kernel hacking
; acestea oferă informații de debug suplimentare, cu dezavantajul unui kernel mai mare și mai lent.
Configurația este salvată în cadrul fișierului .config
din directorul rădăcină al surselor. Este indicat să se realizeze un backup al acestui fișier înainte de configurare pentru a avea o configurație sigură la care să se revină în cazul apariției de probleme.
initrd (initial ramdisk) este un sistem de fișiere temporar având ca suport memoria RAM (ramdisk) care este folosit la pornirea sistemului (booting). Initrd este folosit pentru a încărca driver-ele necesare încărcării sistemului de fișiere rădăcina.
Motivația folosirii initrd este flexibilitatea. Distributiile Linux au un kernel generic Linux care trebuie să boot-eze de pe sisteme cu hardware diferit. Kernel-ul inclus trebuie să fie modular, nefiind posibilă compilarea statică a tuturor opțiunilor fără a mări semnificativ imaginea kernel-ului. Este, în consecinta, necesar să se cunoască la booting locația sistemului de fișiere rădăcină și ce driver-e vor trebui încărcate în kernel. Această problemă este rezolvată prin introducerea initrd ca pas intermediar în pasul de boot-ing. Acesta actioneaza ca un sistem de fisiere rădăcină temporar. Conținutul acestui sistem rădăcină este dat de imaginea de initrd.
De obicei, compilarea unui kernel pentru un sistem dat nu necesită utilizarea initrd, deoarece se cunoaste hardware-ul existent și sistemul de fisiere utilizat. Pentru a se evita utilizarea initrd, vor trebui compilate în imaginea de kernel (built-in) driver-ele de hard-disk, SCSI (dacă există) și de sisteme de fișiere. Daca aceste driver-e ar fi compilate ca module atunci ar trebui încărcate de pe hard-disk, făra însă a putea accesa hard-disk-ul (din lipsa driver-elor). În această situație se foloseste initrd. Driver-ele în cauză se găsesc în:
Device Drivers → ATA/ATAPI/MFM/RLL support
- de obicei trebuie compilate built-in driverele IDE specifice hardware-ului folosit pentru a putea beneficia de modurile Ultra DMA. Daca nu, se pot pune driverele generice (generic/default IDE chipset support
și Generic PCI IDE Chipset Support
)Device Drivers → SCSI device support
File systems
(va trebui configurat ca built-in suportul pentru sistemul de fișiere rădăcină)
Pentru utilizarea initrd este necesar pachetul initrd-tools
.
Înainte de compilare, este indicat să se creeze un indicator unic pentru imaginea de kernel creată. Aceasta se poate realiza completând campul EXTRAVERSION din Makefile-ul kernelului. Se poate seta acest camp la orice șir de caractere.
Faza de compilare presupune obținerea imaginii de kernel și compilarea modulelor de kernel. Acest lucru se realizează prin intermediul a doua comenzi:
# make bzImage # make modules
Prima comandă creează o imagine de kernel comprimată. Acest pas poate dura de la câteva minute până la câteva zeci, depinzând de configurația hardware. După încheiere, imaginea comprimată se regasește în arch/i386/boot/bzImage
(pentru o arhitectura x86).
A doua comandă compilează modulele care pot fi încărcate de kernel. Acest pas poate dura de câteva ori mai mult decât pasul precedent. Fișierele obiect ce reprezintă modulele (cu extensia .ko
) rezidă în directoarele asociate, urmând a fi instalate.
Instalarea presupune copierea imaginii de kernel și a modulelor in locurile prevăzute și configurarea bootloader-ului pentru a boot-a noul kernel. Acest pas se leagă de directorul /boot
unde se găsesc toate fișierele importante.
Imaginea de kernel și fișierele asociate sunt copiate în directoarele necesare cu ajutorul comenzii make install
.
Pașii executați prin intermediul comenzii make install
sunt detaliați mai jos.
Imaginea de kernel va trebui copiată în /boot
:
# cd /usr/src/linux # cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.24.2mykernel
(șirul mykernel este folosit pentru identificarea imaginii de kernel; poate coincide cu versiunea locală precizată la configurare)
În plus față de imaginea de kernel, se recomandă copierea fișierului de configurare și a tabelei de simboluri.
# cd /usr/src/linux # cp .config /boot/config-2.6.24.2mykernel # cp System.map /boot/System.map-2.6.24.2mykernel
Instalarea modulelor de kernel se realizează prin intermediul comenzii:
# make modules_install
Modulele sunt instalate in /lib/modules/2.6.24.2mykernel
.
Daca s-a configurat sistemul pentru a folosi initrd, va trebui creată imaginea de ramdisk. Pentru aceasta se ruleaza comanda:
# cd /boot # mkinitramfs -o /boot/initrd.img-2.6.24.2mykernel 2.6.24.2mykernel
Comanda va inspecta directorul /lib/modules/2.6.24.2mykernel
si va crea imaginea de ramdisk corespunzatoare.
Dupa instalarea imaginii de kernel și a modulelor de kernel va trebui configurat bootloader-ul pentru a ști de unde să incarce imaginea la pornirea sistemului.
Vom presupune configurarea GRUB (GRand Unified Bootloader), în detrimentul LILO (LInux LOader), pentru că este mai răspăndit. Configurări pentru LILO se pot găsi și in link-urile de mai jos.
Există două versiuni majore de GRUB, 1 și 2. Mai departe ne vom ocupa de configurare GRUB2.
Pentru a adăuga o intrare în meniul GRUB-ului se editează fișierul /etc/grub.d/40_custom
și apoi se rulează comanda:
# update-grub
Un exemplu de configurare este prezentat în continuare:
[...] menuentry "Linux" { set root=(hd0,1) linux /boot/vmlinuz-2.6.24.2mykernel root=/dev/sda1 initrd /boot/initrd.img-2.6.24.2mykernel }
Opțiunea initrd poate fi omisă în cazul în care nu s-a configurat un ramdisk inițial.
Pentru rularea noului kernel, va trebui repornit sistemul și optat pentru noul kernel din meniul bootloader-ului.
ATENTIE: Se recomandă păstrarea fostului kernel, în cazul în care apar probleme la noul kernel compilat. Probleme pot aparea din neincluderea driver-elor necesare în cazul în care nu se folosește initrd, omiterea driver-ului de sistem de fișiere necesar etc.
E posibil sa avem la dispoziție un kernel care ruleaza dar caruia ii lipsesc funcționalitați (de exemplu networking), pentru ca s-a omis compilarea driver-elor pentru placa de rețea. În acest caz se poate recompila kernel-ul pentru introducerea noilor funcționalități. Noua compilare va dura mai puțin în cazul în care modificările sunt minime.
O metoda de troubleshooting este compararea unei configurații functionale cu cea curentă prin inspecția fișierelor .config
asociate.
În cadrul Windows Academic Program există posibilitatea accesului la codul sursa a kernel-ului de Windows NT, prin intermediul inițiativei Windows Research Kernel (WRK).
Codul sursă prezintă componentele cele mai importante din cadrul nuclelui (managementul memoriei, procese, thread-uri, scheduling, I/O manager) și poate fi folosit și modificat în scopuri non-comerciale. Se pot astfel urmări diversele mecanisme de implementare și design care stau la baza kernel-ului și se pot testa diverse alte soluții prin modificarea surselor. Accesul la sursele kernel-ului este limitat, anumite subdomenii (cum ar fi networking-ul) fiind absente.
Accesul la codul sursă pentru nucleul de Windows NT înseamna posibilitatea de modificare a acestuia și, evident, de compilare a kernel-ului și de boot-are. Sursele sunt accesibile prin intermediul imaginii de CD pusă la dispoziție de Microsoft în cadrul inițiativei WRK.
Din păcate, kernel-ul de Windows nu vine cu opțiuni de configurare, astfel încat procesul se rezumă la rularea comenzii de compilare și la instalarea noului kernel. Dacă se dorește un tip special de funcționalitate vor trebui alterate sursele.
De asemenea, kernel-ul poate fi compilat numai pe un sistem Windows 2003 SP1 sau Windows XP x64. Versiunea curentă (WRK-1.2) nu poate fi compilată pe un sistem Windows XP x86. Sursele sunt disponibile în directorul C:\cygwin\home\Administrator\so2\WRK\
din cadrul mașinii virtuale de Windows.
Etapele de compilare sunt prezentate și în fișierul README.txt din rădăcina surselor.
Pentru compilarea surselor se parcurg următorii pași (vom utiliza de acum inainte %wrk%
ca rădăcina surselor de kernel de Windows):
C:\>set wrk=C:\cygwin\home\Administrator\so2\WRK\WRK-v1.2 C:\>set arch=x86 C:\>set path=%wrk%\tools\%arch%;%path% C:\>cd %wrk%\base C:\cygwin\home\Administrator\so2\WRK\WRK-v1.2\base>cd ntos C:\cygwin\home\Administrator\so2\WRK\WRK-v1.2\base\ntos>nmake -nologo %arch%=
Imaginea de kernel obținută se va regăsi în %wrk%\base\ntos\BUILD\EXE
și va purta numele wrkx86.exe
pentru un sistem cu arhitectura x86. Imaginea obținută este doar nucleul; modulele de kernel folosite vor fi cele existente în sistem în acel moment.
Procesul de instalare presupune copierea imaginii kernel-ului în %SystemRoot%\system32
:
C:\>copy %wrk%\base\ntos\BUILD\EXE\wrkx86.exe %SystemRoot%\system32\
Totuși, în afara imaginii de kernel, va trebui precizată imaginea de HAL (Hardware Abstraction Layer) care va fi utilizată. Va trebui gasită imaginea corecta de HAL; există trei imagini de HAL disponibile in %wrk%\WS03SP1HALS\x86
. Pentru a afla care imagine este cea corectă va trebui utilizat linker-ul (folosind comanda link
și analizată imaginea de HAL existentă în acest moment în sistem).
C:\>"C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" Setting environment for using Microsoft Visual Studio 2005 x86 tools. C:\>link -dump -all %SystemRoot%\system32\hal.dll | findstr pdb 80011530: 68 61 6C 2E 70 64 62 00 00 00 00 00 00 00 00 00 hal.pdb......... 42435B3A cv 20 00001518 918 Format: RSDS, {2ECB059A-3F06-4 285-8E30-3FDE64119692}, 1, hal.pdb
Motivul pentru care în ieșirea comenzii nu apare șirul halaacpi.dll
este că a fost dezactivat ACPI pe mașina virtuală de Windows 2003.
Asocierea dintre ieșirea comenzii de mai sus și imaginile disponibile în %wrk%\WS03SP1HALS\x86
este (după cum este precizat și în README.txt):
halacpi.dll -> halacpim.dll halaacpi.dll -> halmacpi.dll halapic.dll -> halmps.dll
De obicei, imaginea căutată va fi halmacpi.dll
.
Imaginea corectă de HAL va fi copiată tot în %SystemRoot%\system32
:
C:\>copy %wrk%\WS03SP1HALS\x86\halmacpi\halmacpi.dll %SystemRoot%\System32\
Pentru a boota proaspătul kernel va trebui adaugată o intrare în C:\boot.ini
, fișierul de configurare pentru loader-ul de Windows NT. Se recomandă copierea unei linii de bootare existente și modificarea ei pentru a boota noul kernel și noua imagine de HAL, ca mai jos:
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard" /fastdetect /NoExecute=OptOut multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard - WRK-1.2 compiled kernel" /kernel=wrkx86.exe /hal=halmacpi.dll /fastdetect /NoExecute=OptOut
Pentru vizualizarea boot.ini
în Windows Explorer, va trebui să accesați Tools → Folder Options → View → Hide protected operating system files (Recommended)
. Fișierul este implicit read-only; pentru editare va trebui să anulați această opțiune. Alternativ puteți face acest lucru din linia de comanda:
C:\>attrib -h -s -r boot.ini
După configurarea boot.ini
, sistemul poate boota în noul kernel compilat.