22
Referent Klaus Ruhwinkel Kernel Programmierung unter Linux Programmierung von Kernelmodulen für den Raspberry PI

Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Embed Size (px)

Citation preview

Page 1: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Referent Klaus Ruhwinkel

Kernel Programmierung unter Linux

Programmierung von Kernelmodulen für den Raspberry PI

Page 2: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 3: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 4: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Kernelstrukturen

4 Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

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

Page 5: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Komponenten des Linux-Kernel

5 Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

Bibliotheken Service

Systemcall-Interface

I/O-Subsystem Prozess- management

Speicher- management

Gerätetreiber Hardware

Userland

Kernel

Sonstige BS-Komponenten

Grafik entnommen: Linux Treiber entwickeln, Quade u. Kunst

Page 6: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 7: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 8: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 9: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Prozessmanagement III

9

Rechenprozesszustände:

Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

lauffähig/running

aktiv/current

TASK_WAKING

ununterbrechbar UNINTERRUPTIBLE

unterbrecbar INTERRUBTIBLE

ZOMBIE

ruhend/terminiert

exit

wait

Scheduler sleep

sleep

wakeup

fork/clone

Grafik entnommen: Linux Treiber entwickeln, Quade u. Kunst

Page 10: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 11: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 12: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 13: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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, wird die Konfiguration in die Datei .config gespeichert

Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

Page 14: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Voraussetzungen Gerätetreiber III

14 Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

Page 15: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Voraussetzung Gerätetreiber, Device-Tree

15 Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

Die Vielzahl der ARM-Prozessoren führte nicht nur zu einer Überfrachtung der Kernelsourcen sondern auch dazu, dass das eigentliche Ziel „compile once, run everywhere“ 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.

Page 16: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 Raspberry ab 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 12.01.17

Page 17: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Voraussetzungen Gerätetreiber V speziell Raspberry PI

17

•  Sind die Sourcen übertragen werden sie mit dem Befehl tar xfz linux_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/*.dtb /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 12.01.17

Page 18: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Der erste Gerätetreiber I

18 Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

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

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

Page 19: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Der erste Gerätetreiber

19

Das Makefile: Dokumentation:

Documentation/kbuild/

Oder online:

www.kernel.org/doc/Documentation/kbuild

Kaus Ruhwinkel | Kernel Programmierung unter Linux 12.01.17

Page 20: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 12.01.17

Page 21: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

Literatur

21

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

http://lwn.net/Kernel/LDD3/ •  Embedded Linux lernen mt 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 12.01.17

Page 22: Programmierung von Kernelmodulen für den Raspberry PI · • Kopieren Sie den kompilierten Kernel mit dem Befehl cp arch/arm/boot/zImage / boot/linux- • Bearbeiten

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 16.01.17