From 9c7729b91797c028d90462529d81856ecf8a43f9 Mon Sep 17 00:00:00 2001
From: "Hans J. Koch" <hjk@linutronix.de>
Date: Sun, 21 Jun 2009 17:04:17 +0200
Subject: Added kernel-devel/kernel-build

---
 .../kernel-build/handout_kernel-build_de.tex       | 225 ++++++++++++++++++++-
 1 file changed, 219 insertions(+), 6 deletions(-)

(limited to 'kernel-devel/kernel-build/handout_kernel-build_de.tex')

diff --git a/kernel-devel/kernel-build/handout_kernel-build_de.tex b/kernel-devel/kernel-build/handout_kernel-build_de.tex
index 4c391b2..f0e5fae 100644
--- a/kernel-devel/kernel-build/handout_kernel-build_de.tex
+++ b/kernel-devel/kernel-build/handout_kernel-build_de.tex
@@ -1,17 +1,230 @@
-\documentclass{article}
+\documentclass{lxarticle}
 \usepackage{german}
 \usepackage[utf8]{inputenc}
+\usepackage{lxheaders}
+\usepackage{lxextras}
 
 \begin{document}
 
-\section*{Titel}
+\section*{Kernel konfigurieren und kompilieren}
 
-\subsection*{Abschnitt1}
+\subsection*{Vorarbeiten}
 
-Text
+Bevor man einen Kernel konfigurieren kann, sollte man wissen, was man will.
+Das hört sich zunächst nach einer trivialen Binsenweisheit an, kann aber
+manchmal tatsächlich nicht ganz einfach sein.
 
-\subsection*{Abschnitt2}
+Zunächst sollte man möglichst viele Informationen über die fragliche Hardware
+sammeln. Dazu gehört die genaue Prozessorversion sowie Typen und Versionen
+der angeschlossenen Chips. Insbesondere die Chips, die bereits beim Booten
+benötigt werden, sollten klar sein. Dazu gehören auf üblichen PCs der,
+Chipsatz mit ATA/SATA-Controller oder, je nach gewünschter Bootquelle auch
+der USB- oder Netzwerk-Chip.
+
+Bei Embedded Devices kommen oft noch NAND-Controller hinzu. In diesem Fall
+sollte man auch über die genauen Daten der angeschlossenen NAND-Chips
+informiert sein.
+
+Weiterhin muss man sich überlegen, von welchen Dateisystemen man booten
+möchte. Gängige Varianten sind ext2, ext3, NFS, oder NAND-Dateisysteme wie
+jffs2 oder ubifs. FAT eignet sich nicht für ein Linux-Rootfilesystem, da es
+beispielsweise keine Gerätedateien unterstützt. Will man Linux von einem
+USB-Stick booten, so wird man diesen dazu beispielsweise mit einem
+ext2-Dateisystem versehen.
+
+ \subsection*{Kernel-Konfiguration}
+
+Mit diesen Informationen versehen, kann man jetzt die Konfiguration beginnen.
+Dies erfolgt durch Eingabe von
+
+\cmd{make menuconfig}
+
+Abbildung \ref{img:menuconfig} zeigt die oberste Ebene des Menüs, das dann erscheint.
+
+
+\begin{figure}[h]
+\centering
+\includegraphics[width=0.8\textwidth]{images/menu_rt_001.png}
+\caption{Menü zur Kernel-Konfiguration}
+\label{img:menuconfig}
+\end{figure}
+
+Am oberen Rand gibt das Menü eine stichwortartige Erklärung zur Bedienung.
+Man sollte bei der Konfiguration zuerst grundlegende Dinge wie den
+Prozessortyp angeben, da untergeordnete Eigenschaften oder Treiber davon
+abhängig sein können.
+
+\subsection*{Module, ja oder nein?}
+Bei üblichen Kerneln für Desktop-Systeme wird man immer einen Großteil der
+Treiber als Module kompilieren. Solche Rechner besitzen viele Schnittstellen,
+über die man später die Hardware erweitern kann, und kann den Kernel bereits
+mit den möglicherweise vorkommenden Treiber-Modulen ausstatten. Diese werden
+dann nur bei Bedarf nachgeladen.
+
+Bei Embedded Systems ist die Situation anders. Hier ist die Hardware meist
+fest vorgegeben, so dass man schon beim Kompilieren genau weiss, welche Treiber
+benötigt werden. Ausserdem ist der im Rootfs zur Verfügung stehende Platz oft
+beschränkt, man wird hier ungern Speicher für unnötige Treiber-Module
+verschwenden.
+
+Andererseits ist es manchmal praktisch, einen Treiber als Modul vorliegen
+zu haben. Speziell während der Entwicklung eines eigenen Treibers ist es
+vorteilhaft, dass man einfach durch Austausch des Moduls eine neue Version
+ausprobieren kann. Unter Linux muss man dabei nicht einmal neu booten,
+sondern kann einen Treiber mit 
+
+\cmd{modprobe mein\_modul} installieren und mit
+
+\cmd{rmmod mein\_modul} wieder deinstallieren.
+
+Die Entscheidung, ob man einen Kernel ganz ohne Module baut, hängt vom
+Einzelfall ab. Bei Embedded Systems kommt dies aber durchaus öfter vor.
+
+Aus verständlichen Gründen dürfen Treiber, die zum Booten und Mounten des
+Rootfs benötigt werden, niemals als Module gebaut werden!
+
+\subsection*{initrd}
+
+Die Kernel von Distributionen haben das Problem, dass sie auf möglichst vielen
+unterschiedlichen Rechnern booten müssen. Würde man die Treiber für alle
+denkbaren Kombinationen fest in den Kernel einkompilieren, so hätte man einen
+riesigen Kernel, von dem der Großteil des Codes niemals benutzt würde.
+
+Die statt dessen verwendete Lösung besteht in einem Verfahren, bei dem der
+Kernel beim Booten eine RAM-Disk anlegt und diese mit einem vorbereiteten
+Image füllt. Das Image enthält sämtliche in Frage kommenden Treiber als Module.
+Nach dem Booten und dem Mounten des Root-Filesystems kann die RAM-Disk wieder
+aus dem Speicher entfernt werden. Dieses Verfahren nennt man \emph{initrd}
+(von \emph{Initial RAM Disk}).
+
+Wenn man einen Kernel für ein bestimmtes Board selbst kompiliert, braucht man
+nie eine initrd, da man ja genau die richtigen Treiber fest einkompilieren kann.
+
+\subsection*{initramfs}
+
+Ein anderes Verfahren, bei dem der Kernel zunächst eine RAM-Disk anlegt, ist
+\emph{initramfs}. Im Unterschied zu initrd wird diese aber nicht aus einem
+externen Image geladen, sondern das Image wird bereits beim Kompilieren zum
+Kernel dazugelinkt. Auch hier wird der von der RAM-Disk belegte Speicher am
+Ende wieder freigegeben.
+
+Das initramfs wird vom Kernel wie ein normales Root-Filesystem gemountet.
+Üblicherweise verwendet man ein minimales System, etwa basierend auf uclibc
+und einer busybox. Man kann in den Startskripten dieses Minimalsystems jetzt
+Aktionen ausführen, bevor das eigentliche Rootfs gemountet wird.
+
+Eine Anwendung dieses Verfahrens ist ein kleiner Bootkernel, der von einem
+IPL gestartet wird. In seinem initramfs befinden sich Startskripte, die den
+eigentlichen Produktiv-Kernel aus einer beliebigen Quelle nachladen und dann
+per \cmd{kexec} starten. Der Vorteil bei diesem Verfahren ist, dass der
+Bootkernel bereits jeden beliebigen Treiber (beispielsweise einen kompletten
+USB-Stack) enthalten kann, während Bootloader meist nur unvollständig mit
+den gängigsten Treibern versehen sind.
+
+Eine weitere Anwendung sind Firmware-Updates. So könnten die Startskripte
+des initramfs beispielsweise auf einem Server nachschauen, ob Updates
+vorhanden sind, und diese dann anwenden.
+
+\subsection*{Kernel kompilieren}
+
+Nach abgeschlossener Kernel-Konfiguration kompiliert man den Kernel einfach
+durch Eingabe von
+
+\begin{lstlisting}
+make
+\end{lstlisting}
+
+Falls der zum Kompilieren verwendete Rechner mehrere CPUs besitzt, kann man
+den Vorgang beschleunigen, indem man \cmd{make} anweist, mehrere Jobs
+gleichzeitig zu starten. Für die Zahl der Jobs ist eine häufig genannte
+Empfehlung die doppelte Anzahl der CPUs plus eins. Auf einem Dual-Core würde
+man also folgenden Befehl verwenden:
+
+\begin{lstlisting}
+make -j3
+\end{lstlisting}
+
+Will man den Kernel für eine andere Architektur als die des Compile-Rechners
+crosskompilieren, so muss man \cmd{make} mitteilen, mit welcher Toolchain und
+für welche Architektur gebaut werden soll. Damit man die doch etwas länglichen
+Optionen nicht immer wieder von Hand eintippen muss, schreibt man sie am Besten
+in ein kleines Skript, das man dann anstelle von \cmd{make} aufruft. Ein Skript
+für die ARM-Architektur unter Verwendung der Codesourcery-Toolchain 2007q3
+könnte etwa so aussehen:
+
+\begin{lstlisting}
+#!/bin/sh
+
+ARCH="arm"
+CROSS="/opt/arm-2007q3/bin/arm-none-linux-gnueabi-"
+export INSTALL_MOD_PATH="/rfs"
+
+make ARCH=$ARCH CROSS_COMPILE=$CROSS $@
+\end{lstlisting}
+
+Speichert man dies beispielsweise unter dem Namen \cmd{makearm} im
+Hauptverzeichnis der Kernelquellen, so ergibt sich folgender Aufruf:
+\begin{lstlisting}
+./makearm -j3
+\end{lstlisting}
+
+\subsection*{Kernel installieren}
+
+Einen Kernel für den lokalen Rechner (also den, auf dem man auch kompiliert
+hat) installiert man einfach durch Eingabe von
+
+\begin{lstlisting}
+make install
+\end{lstlisting}
+
+Dies führt folgende Aktionen durch (Beispiel für einen Kernel 2.6.30):
+\begin{itemize}
+\item Falls es im Verzeichnis \cmd{/boot} bereits ein \cmd{vmlinuz-2.6.30}
+	gibt, wird es in \cmd{vmlinuz-2.6.30.old} umbenannt
+\item Kopieren von \cmd{arch/<Architektur-Name>/boot/zImage} nach
+	\cmd{/boot/vmlinuz-2.6.30}
+\item Anlegen eines symbolischen Link \cmd{vmlinuz -> vmlinuz-2.6.30} in
+	\cmd{/boot}
+\end{itemize}
+
+Anschliessend darf man nicht vergessen, auch die Module des neuen Kernels
+zu installieren:
+
+\begin{lstlisting}
+make modules_install
+\end{lstlisting}
+
+Dabei werden alle Module (Dateien mit der Endung \cmd{*.ko} in Verzeichnisse
+unter \cmd{/lib/modules/2.6.30/...} kopiert. Ausserdem werden dort
+Zusatzinformationen zu den Modulen und ihren Abhängigkeiten generiert.
+
+\emph{VORSICHT!} Wenn man einen Kernel für eine andere Architektur
+crosskompiliert hat, darf man \emph{NIEMALS} leichtfertig
+\cmd{make modules\_install} aufrufen, da dies ohne weitere Warnung die
+eigenen Module mit den natürlich nicht verwendbaren Modulen der fremden
+Architektur überschreiben würde!
+
+Das oben aufgeführte Skript zeigt die korrekte Vorgehensweise. In der Variablen
+\cmd{INSTALL\_MOD\_PATH} kann man ein anderes Root-Filesystem angeben, in das
+die Module installiert werden sollen. Im Beispiel oben würde der Befehl
+
+\begin{lstlisting}
+./makearm modules_install
+\end{lstlisting}
+
+die Module nach \cmd{/rfs/lib/modules/2.6.30/...} installieren. Hat man sein
+Root-Filesystem per NFS aus diesem Verzeichnis gemountet, so stehen die Module
+sofort und ohne Reboot zur Verfügung. Diese Vorgehensweise hat sich bei der
+Entwicklung von Treibern für Embedded Systems sehr bewährt.
+
+\subsection*{Kontrollfragen}
+
+\begin{enumerate}
+\item Beschreiben Sie Unterschiede zwischen initrd und initramfs.
+\item Warum braucht man bei selbst kompilierten Kerneln in der Regel keine
+	initrd?
+\item Nennen Sie eine Anwendung von initramfs.
+\end{enumerate}
 
-Text
 
 \end{document}
-- 
cgit v1.2.3

