Disassembler

Artificial intelligence is no match for natural stupidity.
11září2015

Kompilace linuxového kernelu


Ti mladí to mají dneska strašně jednoduché. Stáhnou zdrojáky, pustí make a vypadne jim z toho hotový balík. To za našich mladých let se musely nastavovat semafory, přidávaly a odebíraly se různá #define, experimentovalo se s flagy pro kompiler a linker, po všech čertech se sháněly závislosti, hlavičkové soubory a další knihovny a když se sysadmin po třech dnech vítězně vynořil ze serverovny, odnášeli ho rovnou na JIP.

Komplikace kompilace


No dobře, zase až tak starý nejsem, takže za mých mladých let už se kompilovalo se svatou trojicí ./configure, make a make install. Jednou za čtvrtletí se však i já ponořím do dob dávno minulých a v rámci patchfestu kompiluju nejnovější PHP pro AIX, což je ohromná sranda, protože IBM XL C/C++ kompiler se ve výchozím stavu nekamarádí se static inline metodami a linker taky občas netuší, co se po něm chce. Dobré příklady, jak oba dva donutit ke spolupráci, má na svých stránkách Michael Perzl.

Ale zpět k tématu. Samotná kompilace linuxového jádra je strašně jednoduchá. Naproti tomu předkompilační nastavení jsou extrémně složitá. Pokud jste zběhlí v linuxu, ale kernel jste ještě nekompilovali, připravte se tak na tři až čtyři hodinky googlení nejrůznějších zkratek a hesel. Pokud v linuxu zběhlí nejste, pak dobu potřebnou ke vzdělávání navyšte tak na tři až čtyři měsíce. Nebo se na nějaká manuální nastavení můžete taky úplně vyprdnout, zužitkovat nastavení vašeho stávajícího kernelu a rozhodnutí o použití nových featur ponechat ve výchozím stavu, který je většinou poměrně příčetný.

Před tím, než vůbec začnete kompilovat, zvažte, zda je to opravu potřeba. V případě, že vám chybí nějaký ovladač, ale potřebujete mít stabilní a vyvážený systém, je většinou daleko lepší volba zkompilovat samotný ovladač a do stávajícího kernelu ho přes modprobezavést. Pokud ale potřebujete nějakou sadu featur, které vaše stávající jádro nemá nebo prostě za každou cenu musíte mít cutting edge verzi, pak směle do toho. Obligátně přikládám disclaimer, že veškeré změny provádíte na vlastní riziko a už se těším, až si i přes mé varování bude někdo v komentářích stěžovat, že si kvůli mně něco rozbil, podobně jako tomu bylo u článku Jak z Windows 10 udělat desktopový systém.

Make install, not *.war


Budu popisovat kompilaci aktuální mainline verze kernelu 4.2 pro Debian- a RHEL-based systémy. Postup je principálně stejný. Nainstalovat nástroje pro kompilaci a sestavování balíků, stáhnout a rozbalit zdrojáky kernelu, nastavit, zkompilovat, nainstalovat. Tak jdeme na to.

Potřebnou sadu nástrojů na deb-based systémech nainstalujete následovně

apt-get install bc build-essential libncurses5-dev wget

Používáte-li Ubuntu, Mint nebo jinou převážně desktopově zaměřenou distribuci, pravděpodobně se na ní bude bc a wget nacházet už ve výchozí instalaci.

RHELové a CentOSové si pak budou potřebovat stáhnout obdobnou sadu nástrojů

yum groupinstall 'Development Tools'
yum install bc ncurses-devel wget

Samozřejmě by z vývojářských utilit bylo možno vytahat jen ty, které jsou při kompilaci jádra potřeba, ale pokud jste došli do takového stavu, kdy si sami kompilujete kernel, velmi pravděpodobně budete brzo potřebovat zkompilovat i něco jiného, takže jsem si zjednodušil práci a prásknul tam celý metabalík.

V druhém kroku pak stáhnete zdrojové kódy kernelu v požadované verzi z www.kernel.org a stažený archiv rozbalíte.

mkdir ~/src && cd ~/src
wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.2.tar.xz
tar xJf linux-4.2.tar.xz
cd linux-4.2/

Nemáte-li v systému nainstalován žádný balík s kořenovými certifikáty, může vám wget odmítnout službu s tím, že serveru nedůvěřuje. V takovém případě si buď nainstalujte balík ca-certificates (v obou distribucích se jmenuje stejně) nebo spusťte wget s parametrem --no-check-certificate.

Teď to konečně začíná být trochu zajímavé. Máte možnost začít na zelené louce a kernel si nakonfigurovat úplně podle svého. To můžu doporučit jedině skutečně zkušeným sysadminům anebo masochistům, protože těch nastavení jsou tam fakt mraky. Lenošní lidi, jako jsem já, pak mohou pustit

cp /boot/config-`uname -r` .config

čímž do pracovního adresáře zkopírují sadu nastavení stávajícího kernelu. Pak existuje několik možností, jak se v nastavení přehrabovat. Mou nejoblíbenější je skrze

make menuconfig

pustit textové rozhraní používající ncurses s víceúrovňovým menu. Pokud jádro nebudujete k čistě testovacím účelům, pak bych doporučil vypnout kompilaci debugovacích informací. To v menu provedete v Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info. Výsledné soubory budou mít znatelně menší velikost a kernel bude o fous rychlejší. Změněná nastavení si pak samozřejmě nezapomeňte uložit.

Po ukončení konfigurace se můžeme směle pustit do kompilace. Makefile linuxového kernelu má několik velice užitečných build targetů, takže nemusíte jádro instalovat přímo na stroj, kde zrovna jste, ale můžete si zkompilovat a sestavit instalační balík pro balíčkovací systém dle vaší preference a ten si pak odnést na úplně jiné zařízení. Mám rád pořádek, takže builduju do balíčků pokaždé. Protože GNU make už pěkných pár let umí pomocí jobů kompilovat na více jádrech zároveň a váš počítač už také pěkných pár let asi vícejádrový bude, používám takovou malou POSIX-compliant vychytávku k tomu, abych nemusel ručně zjišťovat kolikže to mám zrovna jader.

JOBS=`getconf _NPROCESSORS_ONLN`

Sestavení *.deb balíků pro dpkg odpálíte následovně

make -j${JOBS} deb-pkg

a pro rpm analogicky

make -j${JOBS} rpm-pkg

Samozřejmě si počet paralelních jobů nastavte podle svého, případně můžete parametr úplně vynechat a pak kompilace pojede jak kachňátka v řádku za sebou. Na rychlejších strojích trvá jaderná fúze kolem 10 minut, pomalejší můžou mít hotovo za nějakých 40 minut, takže klidně můžete jít na kafe nebo panáka isopropylu.

Jakmile celá ta paráda doběhne, vypadnou z ní balíčky, které můžete obratem nainstalovat. Na Deb-based systémech hledejte balíčky v nadřazeném adresáři

cd ..
dpkg -i linux-*.deb

zatímco RHEL je způsobně uklidí do rpmbuildu

cd ~/rpmbuild/RPMS/`uname -i`
rpm -Uvh kernel-*.rpm

Na závěr restartujte stroj a za předpokladu, že nemáte nijak znásilněný zavaděč, naběhne vám váš zbrusu nový, blyštivý a voňavý kernel.