This is an old revision of the document!


Laborator Extra - Compilarea kernel-ului

Compilarea kernel-ului Linux

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:

  • utilizarea unor opțiuni de compilare prin care arhitectura procesorului este folosită la maxim (ex: alegerea tipului de procesor - implicit se folosește un procesor generic gen i386)
  • activarea/dezactivarea suportului pentru anumite componente hardware sau software (ex: selectarea anumitor driver-e, selectarea unor anumite protocoale de comunicatie)

În cazul kernel-ului Linux, suportul pentru hardware/software poate să fie:

  • built-in - suportul este inclus direct în imaginea (fisierul) kernel-ului
  • sub forma de module de kernel - suportul se găsește în fișiere separate care se încarcă on-demand

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.

Pregătire

Cerințe hardware și software

Înaintea compilării kernel-ului trebuie verificat dacă sistemul satisface cerințele hardware și software.

Din punct de vedere hardware:

  • deși un sistem Linux minimal poate rula în sisteme cu puțină memorie RAM, cerințele minime pentru o distribuție Linux, în momentul de față, variază în jurul valorilor de 128-256 MB RAM.
  • în funcție de opțiunile alese pentru compilare, spațiul ocupat pe disc poate depăși valoarea de 500 MB - în aceste condiții, se recomandă un minim de 1 GB liber pe hard-disk-ul pe care se realizează compilarea.

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:

  • cerințele de mai sus sunt valabile pentru versiunea de kernel 2.6.31.6.
  • utilitarele e2fsprogs}, jfsutils}, reiserfsprogs}, xfsprogs} sunt folosite pentru sistemul de fișiere asociat
  • ppp} și isdn4k-utils} sunt necesare numai dacă legăturile sistemului la Internet sunt de tip PPP sau ISDN.

Ce hardware există în sistem?

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

Obținerea surselor

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 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.

Configurare

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:

  • absența completă din kernel-ul finit (se apasa n})
  • compilarea acesteia în cadrul imaginii de kernel (built-in) (se apasa y})
  • compilarea acesteia sub forma de modul de kernel (se apasa 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 - ramdisk-ul inițial

  • nitrd (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: *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 (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}. ==== (re)denumirea versiunii de kernel ==== Î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. ==== Compilare ==== Faza de compilare presupune obținerea imaginii de kernel și compilarea modulelor de kernel. Acest lucru se realizează prin intermediul a doua comenzi: <code> # make bzImage # make modules </code> Prima comandă creează o imagine de kernel comprimată. Acest pas poate dura de la cateva minute până la câteva zeci, depinzând de configurația hardware. Dupa încheiere, imaginea comprimată se regasește în bzimage} (pentru o arhitectura x86). A doua comandă compilează modulele care pot fi încărcate de kernel. Acest pas poate dura de cateva ori mai mult decat pasul precedent. Fișierele obiect ce reprezintă modulele (cu extensia ko}) rezidă în directoarele asociate, urmând a fi instalate. ==== Instalare ==== 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. ==== Instalare imagine kernel ==== 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}: <code> # cd /usr/src/linux # cp arch/x86/boot/bzImage /boot/vmlinuz-2.6.24.2mykernel </code> (ș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. <code> # cd /usr/src/linux # cp .config /boot/config-2.6.24.2mykernel # cp System.map /boot/System.map-2.6.24.2mykernel </code> ==== Instalare module de kernel ==== Instalarea modulelor de kernel se realizează prin intermediul comenzii: <code> # make modules_install </code> Modulele sunt instalate in 2.6.24.2mykernel}. Daca s-a configurat sistemul pentru a folosi initrd, va trebui creată imaginea de ramdisk. Pentru aceasta se ruleaza comanda: <code> # cd /boot # mkinitrd -o /boot/initrd.img-2.6.24.2mykernel 2.6.24.2mykernel </code> Comanda va inspecta directorul 2.6.24.2mykernel} si va crea imaginea de ramdisk corespunzatoare. ==== Configurare GRUB ==== 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 40_custom} și apoi se rulează comanda:<code> # update-grub </code> Un exemplu de configurare este prezentat în continuare: <code> […] menuentry “Linux” { set root=(hd0,1) linux /boot/vmlinuz-2.6.24.2mykernel root=/dev/sda1 initrd /boot/initrd.img-2.6.24.2mykernel } </code> Opțiunea initrd poate fi omisă în cazul în care nu s-a configurat un ramdisk inițial. ==== Repornire sistem ==== Pentru rularea noului kernel, va trebui repornit sistemul și optat pentru noul kernel din meniul bootloader-ului. *TENTIE: 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.

Compilarea kernel-ului Windows

Î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 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.

Compilare

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.

Instalare

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\

Configurare boot.ini

Pentru a boota proaspătul kernel va trebui adaugată o intrare în 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.

so2/laboratoare/lab_compilare.1360455039.txt.gz · Last modified: 2013/02/24 17:53 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0