Transcript

Referent Klaus Ruhwinkel

Kernel Programmierung unter Linux

Programmierung von Kernelmodulen für den Raspberry PI

Das Betriebssystem

2

Aufbau des Betriebssystem:

• Es besteht aus den Betriebssystemkern und den sonstigen Betriebssystemkomponenten (Userland)

• Der Betriebssystemkern stellt Dienste über z.B. Systemcalls für sämtliche Applikationen her.• Dadurch ist es möglich Daten auf dem Bildschirm darzustellen, Daten in Dateien

abzulegen etc.

• Das Userland nutzt die Dienste, um damit Systemkonfigurationen und ähnliches vorzunehmen

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Kernelarten

3

Es gibt drei Arten von Kernel:

1. Monolithischer Kernel, dazu zählen die Kernel von Linux und Windows. Diese Kernel übernehmen alle Aufgaben wie Speicher- und Prozessverwaltung und sind auch für die Kommunikation zwischen den Prozessen und zwischen den Prozessen und der Hardware zuständig.

2. Microkernel, dazu zählen die Kernel von QNX, Singularity von Microsoft und Symbian OS. Der Kernel verfügt nur über grundlegenden Funktionen des Speicher- und Prozessmanagement sowie der Prozesskommunikation. Alles andere wird durch Server – Clientsysteme, die im Benutzermodus laufen verwaltet.

3. Hybridkernel, dazu zählen die Kernel von MacOSX, Windows NT, ReactOS.Diese Kernel bilden einen Kompromiss zwischen dem monolithischen Kernel und dem Mircrokernel da.

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Kernelstrukturen

4 Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Grafik entnommen: https://de.wikipedia.org/wiki/Monolithischer_Kernel

Komponenten des Linux-Kernel

5 Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

BibliothekenService

Systemcall-Interface

I/O-Subsystem Prozess-management

Speicher-management

GerätetreiberHardware

Userland

Kernel

Sonstige BS-Komponenten

Grafik entnommen: Linux Treiber entwickeln, Quade u. Kunst

Systemcall-Interface

6

• Applikationen nutzen die Dienste des Betriebssystem über Sytemcalls.

• Technisch ist das eine Art Software-Interrupt, dieser wird in der Regel durch die eingebundenen Bibliotheken ausgeführt.

• Der Kernel selbst führt nach dem Auslösen des Software-Interrupt die zugehörige Interrupt-Service-Routine aus.

• Die entsprechenden Systemcalls in Abhängigkeit der Architektur, finden sich in der Datei <arch/arm/include/asm/unistd.h> die wiederum die Headerdatei <arch/arm/include/uapi/asm/unistd.h> inkludiert.

• Es gibt 392 Systemcalls für die Architektur ARM.

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Prozessmanagement I

7

• Das Prozesssubsystem verwaltet die Prozesse• Die Prozesse werden auch Tasks oder Threads genannt• Jeder Prozess belegt drei Speicherblöcke: Codesegment,

Datensegment und Stacksegment.• Teilen sich mehrere Prozesse das Code- und Datensegment

spricht man von Threads• Prozesse die ein eigenes Datensegment besitzen nennt man

Tasks• Des weiteren verwaltet das Prozesssubsystem die Zustände

der Prozesse. Diese können sein: aktiv, lauffähig(running, schlafend und ruhend.

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Prozessmanagement II

8

• Der Kernel unterteilt den Zustand schlafend in unterbrechbare, nichtunterbrechbares und killable Schlafen.

• Weitere Zustände findet man in der Headerdatei <include/linux/sched.h>- #define TASK_RUNNING 0- #define TASK_INTERRUPTIBLE 1- #define TASK_UNINTERRUPTIBLE 2- #define __TASK_STOPPED 4- #define __TASK_TRACED 8- /* in tsk->exit_state */- #define EXIT_ZOMBIE 16- #define EXIT_DEAD 32- /* in tsk->state again */- #define TASK_DEAD 64- #define TASK_WAKEKILL 128

-…

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Prozessmanagement III

9

Rechenprozesszustände:

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

lauffähig/running

aktiv/current

TASK_WAKING

ununterbrechbarUNINTERRUPTIBLE

unterbrecbarINTERRUBTIBLE

ZOMBIE

ruhend/terminiert

exit

wait

Schedulersleep

sleep

wakeup

fork/clone

Grafik entnommen: Linux Treiber entwickeln, Quade u. Kunst

Speichermanagement

10

• Das Speichermanagement ermöglicht die Reservierung von Speicher.

• Der Zugriff wird überwacht.• Der Speicherbereich wird unterteilt in Kernelspace und

Userspace.• Der Kernel bzw. der Gerätetreiber kann nicht direkt auf den

Speicher einer Applikation zugreifen.• Das Umrechnen der logischen Speicheradressen auf die

physikalischen Adressen wird durch Funktionen im Kernel durchgeführt. Es funktioniert nur im Zustand current einer Task

• Das Speichersubsystem übernimmt das Paging und Swapping, was den Zugriff auf den Speicher durch den Treiber erschwert.

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

IO-Management

11

• Das IO-Management ist für den Datenaustausch zwischen den Programmen und der Peripherie zuständig.

• Das IO-Management stellt ein:• Interface zur systemkonformen Integration von Hardware

• Eine einheitliche Programmierschnittstelle

• Ordnungsstrukturen in Form von Dateien und Verzeichnissen siehe auch /dev/...

zur Verfügung.

Es gibt traditionell Schnittstellen für zeichen- und blockorientierte Geräte. Und eine Vielzahl von Subsystemen die Hardware wie USB, PCI etc. ansprechen.

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Voraussetzungen Gerätetreiber I

12

• Um einen Treiber zu entwickeln benötigen man zuerst die Kernelsourcen, </usr/src/linux>, beachten Sie, das dieses im Allgemeinen ein Link auf die Sourcen ist.

• Hinweis: alle weiteren Angaben zu Dateien und Verzeichnissen sind ab jetzt relativ zum Sourcepfad

• Einen übersetzten Kernel mit Modulen.• Eine Entwicklungsumgebung zur Übersetzung der Sourcen. In

unserem Falle benutzen wir den Crosscompiler.• Den aktuellen Kernel für den Raspberry Pi kann man mit dem

folgendem Befehl laden.• git clone --depth=1 https://github.com/raspberrypi/linux.git

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Voraussetzungen Gerätetreiber II

13

1. Anpassen und Übersetzten eines Kernels• Zum Anpassen wechselt man in das Verzeichnis in dem die

Kernelsourcen liegen.• Durch den Aufruf make menuconfig wird eine grafische

(Ncurses) Oberfläche gestartet. Dazu wir die Bibliothek libncurses5-dev benötigt.

Durch Auswahl von Save, wirddie Konfiguration in die Datei.config gespeichert

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Voraussetzungen Gerätetreiber III

14 Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Voraussetzung Gerätetreiber, Device-Tree

15 Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Die Vielzahl der ARM-Prozessoren führte nicht nur zu einer Überfrachtung der Kernelsourcen sondern auch dazu, dass das eigentliche Ziel „compile once, runeverywhere“ nicht erreicht wurde.

Deshalb bediente man sich der bestehenden Technik die beim Linuxkernel für Power-PC genutzt wurde. Die Hardwarekonfiguration wurde nicht in den Kernel compiliert, sondern man stellt sie in einer Datenstruktur neben dem Kernel im Speicher zur Verfügung. Das ganze passiert während der Startphase durch den Bootloader. Daher muss der Device-Tree für die Hardware auch im unserem Fall im Verzeichnis /boot liegen.

Neben den Device-Trees gibt es noch das Pincontrol-System, das ab der Kernelversion 3.1 eingeführt wurde. Jerder PIN bekommt einen Namen und eine Nummer „PINCTRL_PIN0(0,“A1“)“. Die PIN‘s werden anschließend zu Gruppen zusammengefasst und konfiguriert.

Voraussetzungen Gerätetreiber IV speziell Raspberry PI

16

• In der Datei README finden sich weitere Möglichkeiten die Kernelkonfiguration anzupassen.

• Mit dem Befehl make ARCH=arm bcm2709_defconfig erzeugt man die Konfigurationsdatei .config speziell für den Raspberryab Version 2

• Der Aufruf make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16 erzeugt den Kernel und die Module.

• Jetzt muss noch das Sourceverzeichnis gepackt und auf den PI übertragen werden. Nutzen Sie folgenden Befehle:

• tar cfz linux_cross.tar.gz linux• scp linux_cross.tar.gz pi@raspxx:/home/pi/progs• CROSS_COMPILE ist eine Umgebungsvariabel aus kbuild

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Voraussetzungen Gerätetreiber V speziell Raspberry PI

17

• Sind die Sourcen übertragen werden sie mit dem Befehl tar xfzlinux_cross.tar.gz entpackt.

• Mit uname –a ermittelt man die bereits installierte Kernelversion• Wechseln Sie in das Verzeichnis linux und geben Sie make modules_install ein.• Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage

/boot/linux-<kernel-version>• Bearbeiten der Datei config.txt im Verzeichnis /boot auf dem Raspberry Pi. Das

hinzufügen bewirkt, dass der neu installierte Kernel gestartet wird.• Fügen Sie die Zeile: kernel=linux<kernel version> zB.: linux-4.4.39-v7+• und die Zeile:device-tree=<device-tree-version> z.B.: bcm2709-rpi-2-b.dtb• sudo cp arch/arm/boot/dts/*.dtb /boot/• sudo cp arch/arm/boot/dts/overlays/*.dts /boot/overlays

• Rebooten Sie das System GOOD LUCK!!!• Loggen Sie sich wieder ein und überprüfen Sie die Version

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Der erste Gerätetreiber I

18 Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

module_init() und module_exit() sind Funktionendie Funktionen bekanntgeben, um den Treiber zuinitialisieren und aus dem Kernelspace zu entfernen.Sie nutzen spezielle Kernelmakros um die Rollen derFunktionen zu identifizieren.

printk() ist ein Pendant zu printf(), nur das printk()speziell für den Kernel ist, da er sich nicht derC-lib bedient.

Der erste Gerätetreiber

19

Das Makefile:

Dokumentation:

Documentation/kbuild/

Oder online:

www.kernel.org/doc/Documentation/kbuild

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Tools zum Einbinden und Entfernen von Modulen

20

• insmod bindet das Modul in den Kernel ein• rmmod entfernt das Modul aus dem Kernel• lsmod zeigt die geladenen Module an• modinfo gibt Informationen zu dem Modul aus • modprobe lädt und entfernt Module aus dem Kernel• Fehlersuche:• Der syslog Dämon zeigt die Ausgabe der Befehle in

/var/log/messages an• dmesg

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Literatur

21

• Linuxsourcen• http://kernelnewbies.org• Ldd3: Linux Device Driver 3rd Edition

http://lwn.net/Kernel/LDD3/• Embedded Linux lernen mit dem Raspberry Pi, Jürgen Quade,

ISBN 978-3-86490-143-0, Ergänzungen und Downloads zum Buch https://ezs.kr.hsnr.de/EmbeddedBuch/

• Linux Treiber entwickeln, Jürgen Quade u. Eva-Katharina Kunst, ISBN 978-3-89864-696-3, Ergänzungen und Downloads zum Buch https://ezs.kr.hsnr.de/TreiberBuch/

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18

Literatur

22

https://github.com/raspberrypi/documentation/blob/master/linux/kernel/building.md

http://www.linux-magazin.de/Ausgaben/2013/06/Kern-Technik

Jake Edge, "ARM and defconfig files": http://lwn.net/Articles/391372/

Das U-Boot: http://www.denx.de/wiki/U-Boot

BCM 2835: http://www.broadcom.com/products/BCM2835

Pincontrol-Subsystem – Dokumentation im Kernel-Quellcode: http://lxr.free-electrons.com/source/Documentation/pinctrl.txt

Raspbian: http://www.raspbian.org

"How to boot using device tree": https://github.com/raspberrypi/linux/wiki/How-to-boot-using-device-tree

Device Tree Usage: http://elinux.org/Device_Tree_Usage

J. Quade, K. Kunst, "Linux-Treiber entwickeln", 3. Auflage: Dpunkt-Verlag 2011; S. 113 ff.

"A Tutorial on the Device Tree (Zynq)": http://xillybus.com/tutorials/device-tree-zynq-1

https://www.raspberrypi.org/documentation/configuration/config-txt.md

http://www.golem.de/news/raspberry-pi-der-mit-dem-64-bit-kernel-tanzt-1611-124475.html

http://www.yoctoproject.org/docs/2.2/mega-manual/mega-manual.html

Kaus Ruhwinkel | Kernel Programmierung unter Linux 14.01.18


Recommended