Hrátky s jadrom
Väčšina súčasných distribúcií používa pre zavedenie systému jadro rozdelené na dve časti samotné jadro a inicializačný RAM disk. Pre bežného používateľa často veci zaradené do kategórie nedotýkať sa. Avšak nie je to až taká mágia, ako sa na prvý pohľad môže zdať a v tomto článku s pokúsim ukázať, ako si možno tieto dve veci prispôsobiť na vlastný obraz.
Obsah článku
Potrebujem to?
Krátka odpoveď znie nie. Dlhšia odpoveď znie možno a úplná odpoveď znie závisí na tom, čo od svojho systému očakávate. Manipulácii s inštaláciou jadra sa nevyhnete v situácii, keď niečo nefunguje.
Niekedy po aktualizácii jadra môžu nastať napríklad problémy, a to najmä v prípade, keď používate ovládače (moduly jadra), ktoré nie sú súčasťou distribúcie. V takom prípade nie je pri aktualizácii jadra automaticky vybudovaný nový modul jadra a po nadšenom reštarte do nového jadra sa začínajú diať veci… Iný prípad je, keď máte hardvér, ktorého ovládače existujú vo viacerých verziách, či vyžadujú špeciálne parametre. No a, v neposlednom prípade, sa do takýchto experimentov pustíte, keď si chcete optimalizovať beh systému alebo prosto len tak, aby ste objavili niečo nové.
Jadro a moduly
Začnem trochu kontroverznou témou, za ktorú považujem moduly jadra. Existujú viac-menej dve hraničné skupiny používateľov. Jedni ich považujú za super vec, druhí zase za pohromu. V podstate sa jedná najmä o moduly ovládačov hardvéru, či súborových systémov a podobne. Tieto veci môžu byť zabudované priamo do jadra a vtedy sú vždy načítané do pamäti spolu s jadrom. Druhý spôsob je ich kompilácia ako modulov jadra a potom bývajú načítané až keď ich je naozaj treba alebo ak je to nastavené. To, či bude nejaká časť vybudovaná ako modul alebo zakompilovaná priamo do jadra, sa nastavuje pri konfigurácii kompilácie jadra.
Upozornenie
Nebudem sa tu zaoberať rekompiláciou jadra, a teda nebudem popisovať ako meniť, či tá ktorá časť je súčasťou jadra alebo je to modul. Naproti tomu sa uspokojím s tým, ako vývojari jadra rozhodli a zhrniem čo sa s tým dá robiť, a to najmä ohľadom ovládačov hardvéru.
Práca s modulmi
Väčšinou je práca s modulmi ovládačov pre používateľa transparentná,
čiže používateľ ani nevie, čo a kedy sa načíta (o ich načítanie sa
stará udev). Niekedy je však potrebné príslušný modul načítať ručne,
napríklad keď hľadáte, ktorý je ten správny. V takom prípade poslúžia
nástroje modprobe a insmod. Príkaz comm;modprobe`
slúži na načítanie (ale aj na uvoľnenie) modulu pomocou jeho mena. Príslušné
moduly hľadá v adresári /lib/modules/$(uname -r)
a meno modulu stačí
zadať bez prípony, napríklad načítanie proprietárneho ovládača grafických kariet
nVidia zaistí príkaz:
modprobe nvidia
Rovnaký nástroj možno použiť aj na uvoľnenie načítaného modulu:
modprobe -r nvidia
Správanie modprobe je možné modifikovať pomocou mnohých parametrov príkazového riadku (viac v man modprobe) a spolu s menom modulu je možné zadať aj parametre modulu.
Ako som spomenul vyššie, nástroj modprobe hľadá zadaný modul v adresári modulov jadra, ak ste si skompilovali modul sami a ešte nie je nainštalovaný v tomto adresári, poslúži nástroj insmod, ktorý načíta modul jadra zadaný menom súboru (aj s príponou), a tak môže byť tento modul uložený na ľubovoľnom mieste:
insmod /usr/src/moj_super_modul.so
Nástroj insmod neposkytuje žiadne parametre príkazového riadku, ale i pomocou tohoto nástroja možno zadať parametre modulu.
Spomínal som parameter -r príkazu modprobe;, ktorý slúži na uvoľnenie modulu z jadra. Aj odstraňovanie modulov má svoju nízkoúrovňovú verziu, a to :command:`rmmod:
rmmod nvidia
Ak chcete preskúmať, aké moduly má vaše jadro práve načítané, poslúži
príkaz lsmod, ktorý vypíše zoznam všetkých načítaných modulov,
vrátane niekoľkých informácií o nich (vlastne len čitateľnejšie
interpretuje obsah /proc/modules
):
lsmod
Module Size Used by
rfcomm 29581 0
l2cap 24736 6 bnep,rfcomm
bluetooth 41827 6 sco,bnep,rfcomm,l2cap
rfkill 13044 2 bluetooth
Tento výpis je samozrejme skrátený, ale vidno na ňom, že výpis je rozdelený do troch (štyroch) stĺpcov. V prvom je meno modulu, nasledované jeho veľkosťou. Na konci sú informácie o závislostiach, najprv je počet modulov, ktoré ho využívajú, nasledovaný zoznamom modulov, ktoré sám používa (nemusí na nich nutne aj závisieť).
Popis príkazov pre prácu s modulmi jadra uzatvorím programom depmod,
ktorý slúži na generovanie súboru modules.dep (súbor s popisom
závislostí modulov) a súboru map. Tento príkaz možno spustiť s menom
súboru modulu, čím je preskúmaná závislosť len tohoto modulu, ale asi
najčastejšie použitie bude s voľbou -a, ktorá sa postará o prejdenie
všetkých modulov v adresári /lib/modules/$(uname -r)
(vlastne pomocou
týchto závislostí dokáže modprobe nájsť správny súbor):
depmod -a
Príkaz depmod je vhodné spustiť po každej manuálnej inštalácii nejakého modulu.
Zakazovanie modulov
Niekedy je snaha vývojárov distribúcie márna a sada modulov nevyhovuje
vášmu hardvérovému vybaveniu, napríklad preto, že na niektorý hardvér
existuje viacero ovládačov a ako natruc sa načíta práve ten, ktorý sa
nemá alebo ktorý nechcete. Túto situáciu je možné riešiť pomocou
zakázania načítania modulu direktívou blacklist, nasledovanou menom
modulu. Túto direktívu môžete nájsť aj v súbore
/etc/modprobe.d/blacklist.conf
. Tento súbor je však súčasťou balíka
udev a jeho zmeny môžu byť stratené pri aktualizácii balíka.
Vhodnejší spôsob je vytvoriť si v tomto adresári nový súbor, ktorý môžete nazvať ako chcete, ale musí mať príponu .conf, napríklad pre zakázanie načítania modulu nouveau bude tento súbor obsahovať:
blacklist nouveau
Takýmto spôsobom zakázané moduly nebudú zahrnuté ani do initrd
.
Parametre modulov
Niektorým modulom je potrebné definovať parametre, ktoré pri jeho
načítaní ovplyvnia jeho správanie. Ako som spomínal vyššie, tieto
parametre možno zadať pri načítaní modulu pomocou programov modprobe,
či insmod. Lenže pre automatické načítanie modulov nám takáto možnosť
nepostačí, ale rovnako ako pri zakazovaní modulov, aj pre tento účel
si môžeme vytvoriť súbor v adresári /etc/modprobe.d/
(tiež s príponou
.conf
), tentokrát však s direktívou options, nasledovanou menom
modulu a príslušnými voľbami.
Aké sú parametre modulov? Toto je síce ľahká a logická otázka, ale nie vždy ľahko zopovedateľná. Jednou z možností, je nájsť príslušné voľby na internete, kde sa odpovede povaľujú na rôznych fórach, alebo preskúmať zdrojový kód modulu (často obsahuje súbor s popisom volieb). Inou možnosťou je použiť program modinfo, ktorý zobrazuje rôzne informácie o súbore modulu, vrátane možných volieb:
modinfo nouveau
filename: /lib/modules/2.6.32-5-amd64/kernel/drivers/gpu/drm/nouveau/nouveau.ko
license: GPL and additional rights
description: nVidia Riva/TNT/GeForce
author: Stephane Marchesin
alias: pci:v000012D2d*sv*sd*bc03sc*i*
alias: pci:v000010DEd*sv*sd*bc03sc*i*
depends: drm,drm_kms_helper,ttm,i2c-core,button,i2c-algo-bit
vermagic: 2.6.32-5-amd64 SMP mod_unload modversions
parm: ctxfw:Use external firmware blob for grctx init (NV40) (int)
parm: modeset:Enable kernel modesetting (int)
parm: vbios:Override default VBIOS location (charp)
parm: vram_pushbuf:Force DMA push buffers to be in VRAM (int)
parm: vram_notify:Force DMA notifiers to be in VRAM (int)
parm: duallink:Allow dual-link TMDS (>=GeForce 8) (int)
parm: uscript_lvds:LVDS output script table ID (>=GeForce 8) (int)
parm: uscript_tmds:TMDS output script table ID (>=GeForce 8) (int)
parm: ignorelid:Ignore ACPI lid status (int)
parm: noaccel:int
parm: noagp:Disable AGP (int)
parm: nofbaccel:int
parm: tv_norm:Default TV norm.
Supported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,
hd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.
Default: PAL
*NOTE* Ignored for cards with external TV encoders. (charp)
parm: reg_debug:Register access debug bitmask:
0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,
0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,
0x100 vgaattr, 0x200 EVO (G80+). (int)
Nástroj modinfo je určený skôr pre skúsených používateľov. V lepšom prípade popis volieb obsahuje aj zoznam možných hodnôt, ale nie je to pravidlo. Našťastie som tieto voľby potreboval vlastne len raz, a to na nastavenie typu zvukovej karty (teda počtu výstupov).
Automatická aktualizácia modulov
Ako možno vyplynulo z predchádzajúceho textu, hoci som to výslovne nespomenul, je, že modul musí byť skompilovaný pre príslušnú verziu jadra. Ak používate len distribučné verzie modulov, nebýva to problém, pretože vývojári Debianu odvádzajú kvalitnú prácu a spolu s novou verziou jadra poskytujú aj nové verzie modulov. Lenže sloboda Linuxu spočíva v tom, že túto prácu vývojárov distribúcie (nie len Debianu) môžete využiť, ale nie ste na ňu odkázaní a môžete do jadra doplniť prakticky čokoľvek. Lenže, vždy po aktualizácii jadra je potrebné túto kompiláciu vykonať znova, čo môže byť nie len nepríjemné, ale často to môže aj poriadne skomplikovať život (napríklad taký ovládač sieťovej karty, ktorý môže spôsobiť dočasnú nefunkčnosť internetu a tým nemožnosť napríklad stiahnuť zdrojový kód modulu).
Jednou z možností ako túto prácu zautomatizovať je použiť možnosť
automatického spúšťania skriptov pri inštalácii či odinštalovaní
príslušnej verzie jadra. Tieto skripty je možné umiestniť do adresárov
/etc/kernel/postinst.d
na automatickú inštaláciu a
/etc/kernel/postrm.d
na automatické odinštalovanie. Ja tieto skripty
využívam pre automatickú prácu s modulmi pre VirtualBox a grafickú
kartu nVidia. Skriptom v týchto adresároch sú posielané i parametre,
prvým parametrom je verzia jadra v tvare, aký vráti príkaz uname -r
a druhým je cesta k jadru.
Nebudem v tomto článku popisovať konkrétny skript, ale poskytnem len
príklad ukážkového skriptu, ktorý vypíše informácie niektoré
informácie do /var/log/syslog
:
#!/bin/bash
# Jednoduchý ukážkový skript /etc/kernel/postinst.d/test
# Jeho jedinou úlohou je vypísať verziu inštalovaného jadra do syslog
VERZIA="$1"
# verzia jadra je vyžadovaná
[ -z "${VERZIA}" ] && exit 0
logger -s -t "driver info" "Spustený poinštalačný hook pre jadro $VERZIA" >&2
exit 0
Ak chcete funkčnosť tohoto súboru vyskúšať, nemusíte inštalovať nejakú inú verziu jadra (ako je v mnohých návodoch), plne stačí spustiť rekonfiguráciu aktuálneho jadra:
dpkg-reconfigure linux-image-$(uname -r)
Pozor na kombináciu vkladania modulov do initrd, pretože tieto skripty sa spúšťajú až po generovaní initrd. Ak teda chcete (potrebujete) do initrd vložiť modul, ktorý je generovaný takýmto skriptom, je poterbné pridať i opätovnú generáciu initrd.
Inicializačný RAMdisk
Hoci je stále možné zakompilovať všetko do jediného súboru jadra, v súčasných linuxových distribúciách sa s tým môžete stretnúť len vo výnimočných prípadoch (väčšinou distribúcie na špeciálne účely) a je použitý inicializačný RAM disk. Tento inicializačný RAMdisk (initrd) sa načíta do pamäte ihneď po načítaná jadra a slúži ako počiatočný inicializačný koreňový adresár. Obsahuje moduly, ktoré sú potrebné pri štarte jadra, ale najmä pre pripojenie reálneho koreňového súborového systému.
V Debiane sa ním potrebujete zaoberať len výnimočne, pretože o všetko
sa transparentne (pre používateľa) postará inštalačný systém jadra a
pri inštalácii alebo aktualizácii jadra, či niektorých modulov
automaticky spustí generovanie alebo aktualizáciu initrd
. Na
manipuláciu s týmto initrd slúži balík initramfs-tools a pri jeho
inštalácii(väčšinou už pri inštalácii systému) sa pýta na to, či
vložiť do initrd všetky moduly alebo len tie potrebné. Teraz ruku na
srdce, keď ste na túto otázku odpovedali, vedeli ste ktorá voľba je
správna?
Nech už ste odpovedali tak, či onak, je to samozrejme možné zmeniť, a
to v súbore /etc/initramfs-tools/initramfs.conf
. Tento súbor obsahuje
viacero konfiguračných volieb, ale asi najdôležitejšia je voľba
MODULES. Môže nadobúdať jednu zo štyroch hodnôt:
- most – pridá moduly väčšiny súborových systémov a všetkých ovládačov pevných diskov
- dep – pridá len potrebné moduly
- netboot – pridá sieťové moduly a vynechá moduly pevných diskov
- list – pridá len moduly zo zoznamu
Voľba most je vhodná na univerzálny systém, kde sa môže meniť konfigurácia diskov a poskytuje istotu, že sa pri štarte spustia všetky potrebné moduly. Naproti tomu voľba dep poslúži na ustálený systém, ale prináša riziko, že systém nemusí naštartovať (pravdepodobnosť je veľmi nízka, ale je). Bežný stolný počítač bude spoľahlivo fungovať s obomi týmito voľbami, a ak vám nezáleží na veľkosti súboru (závisí na tom doba načítania a dekomprimácie), nemusíte ich vôbec riešiť. Voľba netboot poslúži pri štarte po sieti a voľba list je vhodná pre expertov.
Napriek tomu, že initramfs-tools spoľahlivo vloží do initrd potrebné
moduly, môžu nastať situácie, v ktorých je potrebné ručne pridať
niektorý modul. Pre tento účel je určený súbor /etc/initramfs-tools/modules
,
do ktorého stačí pridať zoznam dodatočných (alebo všetkých pri voľbe list)
modulov. A samozrejme vygenerovať nový initrd:
update-initramfs -u
Voľba -u udáva aktualizáciu súboru intrd
(/boot/initrd.img-[verzia]-]architektúra]), ak chcete vygenerovať nový
initrd, použite voľbu -c. V oboch prípadoch sa vo východzom nastavení
jedná o initrd pre aktuálne bežiace jadro. Ak máte v systéme viacero
jadier, a chcete aby boli aktualizované initrd pre všetky jadrá,
musíte zmeniť voľbu pre update-initramfs v súbore
/etc/initramfs-tools/update-initramfs.conf
. Táto voľba môže nadobúdať
jednu z troch hodnôt:
- yes – pre povolenie aktualizácie initrd pri aktualizácii jadra
- no – pre zakázanie aktualizácie initrd
- all – pre povolenie aktualizácie initrd, ale pre všetky nainštalované jadrá
Istý čas som mal dve jadrá a každom mi fungoval iný kus hardvéru (ktorý nefungoval v tom druhom), vtedy som automatickú aktualizáciu oboch initrd ocenil.
Súčasný súbor initrd v Debiane je komprimovaný archív cpio. Typ
komprimácie udáva voľba COMPRESS v súbore initramfs.conf
(gzip). Túto
informáciu oceníte najmä v prípade, že sa pustíte do experimentovania
s initrd a budete si chcieť pozrieť, čo všetko obsahuje, pretože na
základe vedomosti o štruktúre súboru initrd si ho možno ľahko rozbaliť
a následne preskúmať:
mkdir /tmp/initrd
cd /tmp/initrd
zcat /boot/initrd.img-[verzia]-[architektúra] | cpio -i
Staršie verzia jadra používali komprimovaný alebo nekomprimovaný obraz
súborového systému, ktorý bolo potrebné pripojiť pomocou zariadenia
loop
.
Záver
Možno som to mal napísať na začiatku, ale možno vám to vôbec
nechýbalo, ale pre úplnosť ešte uvediem, predvolený adresár so súbormi
jadra a initrd je adresár /boot
. V tomto adresári sú súbory jadra
pomenované vmlinuz-*
a súbory initrd, pomenované initrd.img-*
.
Oba obsahujú za pomlčkou číslo verzie a architektúru, napríklad:
initrd.img-2.6.32-5-amd64
vmlinuz-2.6.32-5-amd64
Samozrejme, toto pomenovanie platí len pre distribučné jadrá, ak používate vlastné, môže sa volať úplne inak a byť uložené úplne inde.