diff options
Diffstat (limited to 'kernel-devel/kernel-build')
| -rw-r--r-- | kernel-devel/kernel-build/Makefile | 9 | ||||
| -rw-r--r-- | kernel-devel/kernel-build/handout_kernel-build_de.tex | 225 | ||||
| -rw-r--r-- | kernel-devel/kernel-build/images/menu_rt_001.png | bin | 0 -> 30735 bytes | |||
| -rw-r--r-- | kernel-devel/kernel-build/pres_kernel-build_de.tex | 27 |
4 files changed, 241 insertions, 20 deletions
diff --git a/kernel-devel/kernel-build/Makefile b/kernel-devel/kernel-build/Makefile new file mode 100644 index 0000000..d221473 --- /dev/null +++ b/kernel-devel/kernel-build/Makefile @@ -0,0 +1,9 @@ +all: + pdflatex pres_kernel-build_de.tex + pdflatex hints_kernel-build_de.tex + pdflatex handout_kernel-build_de.tex + pdflatex handout_kernel-build_de.tex + +clean: + rm -f *.aux *.log *.pdf *.log *.snm *.toc *.vrb *.nav *.out + 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} diff --git a/kernel-devel/kernel-build/images/menu_rt_001.png b/kernel-devel/kernel-build/images/menu_rt_001.png Binary files differnew file mode 100644 index 0000000..27f26cd --- /dev/null +++ b/kernel-devel/kernel-build/images/menu_rt_001.png diff --git a/kernel-devel/kernel-build/pres_kernel-build_de.tex b/kernel-devel/kernel-build/pres_kernel-build_de.tex index 07db328..1489f12 100644 --- a/kernel-devel/kernel-build/pres_kernel-build_de.tex +++ b/kernel-devel/kernel-build/pres_kernel-build_de.tex @@ -1,24 +1,23 @@ -\documentclass{article} +\documentclass{beamer} +\usetheme{linutronix} \usepackage{german} \usepackage[utf8]{inputenc} +\usepackage{pgf} +\usepackage{graphicx} +\usepackage{lxextras} -\begin{document} - -\section*{Block \lq Was ist Linux?\rq} +\title{Linux-Kernel konfigurieren und kompilieren} +\institute{Linutronix GmbH} -\subsection*{Lernziele} -\begin{itemize} -\item Lernziel 1 -\item Lernziel 2 -\item Lernziel 3 -\end{itemize} +\begin{document} -\subsection*{Unterrichts-Ablauf} +\maketitle -Hinweise zur Präsentation, Zeitplanung, etc. -\subsection*{Übungen bei vorhandener Hardware} +% ----- Slide ------------------ +\begin{frame} +\frametitle{Hallo} +\end{frame} -Hinweise zu Übungen, Zeitlimit dazu. \end{document} |
