Kernel Programmierung unter Linux Teil II Programmierung von Kernelmodulen

Kernel Programmierung unter Linux Teil II Programmierung von Kernelmodulen Referent Klaus Ruhwinkel Module, Built-In-Treiber, Treiber •  Ein...
Author: Herbert Winter
6 downloads 0 Views 200KB Size
Kernel Programmierung unter Linux Teil II Programmierung von Kernelmodulen

Referent

Klaus Ruhwinkel

Module, Built-In-Treiber, Treiber

•  Ein Modul kann alles sein •  Ein Treiber hat I/O Aufgaben und unterscheidet sich so zum Modul •  Built-In-Treiber sind fest in den Kernel integriert, eine Änderung im Treiber setzt das neue Übersetzten des Kernel voraus •  Vorteile von ladbarem Code •  Das neue Übersetzen des Kernels ist nicht notwendig, •  damit braucht das System nicht neu gestartet werden •  direkter Zugriff auf das Modul nach dem Laden.

2

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Fehlersuche I

•  Debugger •  Mit dem Kerneldebugger kgdb •  Problem: es werden zwei Rechner benöQgt, Zielsystem und Host sind mit einer seriellen SchniSstelle verbunden. •  er ist noch experimentell •  und steht nicht für alle PlaWormen zur Verfügung.

•  Mit dem Built-In-Debugger •  Problem Fehlersuche auf Assemblerebene •  Kernelsourcen müssen gepatcht werden •  DokumentaQon findet man unter DocumentaQon//kdb •  Debuggen nicht im X-Window, es ist nur über die Konsole möglich

3

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Fehlersuche II

•  printk(...) •  AkQve Fehlersuche mit der KernelfunkQon printk(...) •  Die Ausgabe von printk() wird in die Datei, abhängig von der DistribuQon, durch den rsyslog-Daemon in die Datei /var/log/messages bzw. in die Datei / var/log/syslog oder auch /var/log/kern.log geschrieben. •  KonfiguraQonsdatei für den rsyslog-Daemon ist /etc/syslog.conf oder im Verzeichnis /etc/syslog.d/... Befinden sich KonfiguraQonsdateien für verschiedene Programme etc. •  Die Loglevel des Kernels sind in der Datei include/linux/kern_levels.h definiert. Auszug aus der Headerdatei: •  #define KERN_EMERG KERN_SOH "0" /* system is unusable */ •  #define KERN_ALERT KERN_SOH "1" /* acQon must be taken immediately */ •  #define KERN_CRIT KERN_SOH "2" /* criQcal condiQons */

4

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Fehleruche III

•  Besser ist die bedingte Übersetzung mit dem Präprozessor •  Dazu werden Makros aus den Headerdateien kernel.h und device.h genutzt •  pr_debug("Modul entladen\n");

•  Diese Headerdateien müssen dazu mit #include eingebunden werden •  Das einfügen der Makros bedarf der zusätzlichen Variable EXTRA_CFLAGS im Makefile •  EXTRA_CFLAGS=-DDEBUG •  Beispiele für Makros aus der Datei include/linux/kernel.h •  #define dev_emerg_once(dev, fmt, ...) • 

dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__)

•  #define dev_alert_once(dev, fmt, ...) • 

5

\

dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__)

•  #define dev_err_once(dev, fmt, ...) • 

\

dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__)

•  #define dev_crit_once(dev, fmt, ...) • 

\

dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__)

Kaus Ruhwinkel | Kernel Programmierung unter Linux

\

Kernelcode kodieren •  Innerhalb des Betriebssystemkerns steht die Standard C-Bibliothek nicht zur Verfügung •  Es gibt aber definierte FunkQonen im Verzeichnis lib/ zum Beispiel findet man dort die Datei string.c

•  Im Kernel wird bevorzugt mit Ganzahlen gerechnet •  Es gibt im Kernelbereich begrenzte Speicherresourcen, größere Speicherreservierungen sind mit kmalloc(...) zu reservieren. •  Im Kernelbereich gibt es keinen Speicherschutz! •  Goto ist zu verwenden, wenn es dem Programmfluss förderlich ist •  Objektbasierte Programmierung und Entwurfsmuster im Kernel •  Es ist auf eine strikte Trennung zwischen den Daten und dem Code zu achten. •  Es gibt also einen Objektdatenbereich und ein ObjekqunkQonsbereich

6

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Gerätenummern

•  Den Modulen kann man selbst Gerätenummern in der init-FunkQon mitgeben, bzw. man kann sie durch den Kernel generieren lassen. •  Die Gerätenummern werden unterschieden in Major- und Minornummern.

7

Auszug aus /dev/ : c steht für Charakter Device Bsp: Device hpet: Major-Nr 10 Minor-Nr 228 Device lp0: Major-Nr 6 Minor-Nr 0 Kaus Ruhwinkel | Kernel Programmierung unter Linux

Gerätenummeren II

Die Gerätenummern können auf zwei Arten reserviert werden. Manuell: Es ist vorher zu prüfen ob die Majornummer vergeben ist.



Dazu kann die Datei /proc/modules genutzt werden.

int register_chrdev_region(dev_t first, unsigned int count, char *name); AutomaEsiert: int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); 8

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Gerätenummern III

Beispiel Manuel: sta9c dev_t fastgpio_dev_number = MKDEV(247,0); if( register_chrdev_region(fastgpio_dev_number,1,"fastgpio") Char Device RegistraQon enthält die Stuktur cdev, welche der Kernel für die RepräsentaQon von char-devices benöQgt. struct cdev { struct kobject kobj; struct module *owner; const struct file_opera9ons *ops; struct list_head list; dev_t dev; unsigned int count; }; und zusätzliche FunkQonen, zur Erzeugung, Löschung dieser Objekte



11

Kaus Ruhwinkel | Kernel Programmierung unter Linux

BenöEgte Headerdateien und Strukturen II:

include/linux/fs.h -> Filesystem Header enthält wichQge Strukturen und FunkQonen zum Schreiben von Devices. Wie: int register_chrdev_region(dev_t first, unsigned int count, char *name); und die Struktur: sta9c struct file_opera9ons 12

Kaus Ruhwinkel | Kernel Programmierung unter Linux

BenöEgte Headerdateien und Strukturen III:

Include/linux/device.h -> device.h - generic, centralized driver model ist die zentrale Headerdatei für Devices Include/linux/gpio.h -> General Purpose Input / Output ist die Headerdatei in der Strukturen und FunkQonen zur ManipulaQon der I/O‘s sta9c inline int gpio_request(unsigned gpio, const char *label) fängt Systemerror sta9c inline int gpio_direc9on_output(unsigned gpio, int value) iniQalisiert den Ausgangswert sta9c inline void gpio_free(unsigned gpio) gibt den Port frei sta9c inline void gpio_set_value(unsigned gpio, int value) setzt den Ausgang

13

Kaus Ruhwinkel | Kernel Programmierung unter Linux

BenöEgte Headerdateien und Strukturen IV:

asm/uaccess.h -> user space memory access funcQons unsigned long copy_to_user(void _ _user *to, const void *from, unsigned long count); unsigned long copy_from_user(void *to, const void _ _user *from, unsigned long count); count ist die Anzahl der Bytes, die kopiert werden, Rückgabewert ist die Anzahl der nicht kopierten Zeichen, ansonsten null. 14

Kaus Ruhwinkel | Kernel Programmierung unter Linux

BenöEgte FunkEonen und Strukturen I:

Es werden die untenstehenden FunkQonen für den Device-Treiber benöQgt: mod_init(): Makro das den Treiber IniQalisiert mod_exit(): Makro das den Treiber enqernt FunkQonen die durch Systemcalls angesprochen werden: driver_close() driver_open() driver_write()

15

Kaus Ruhwinkel | Kernel Programmierung unter Linux

BenöEgte FunkEonen und Strukturen II:

Die Struktur file_operaQons. In dieser Struktur werden die korrespondierenden FunkQonen beschrieben, die über Systemcalls aufgerufenen werden. sta9c struct file_opera9ons fops = { .owner = THIS_MODULE, .open = driver_open, .release= driver_close, .write = driver_write, };



16

Kaus Ruhwinkel | Kernel Programmierung unter Linux

Beispiel

Beispiel Zugriff auf GIO Bus: Wählen Sie die Beispiele unter 6.2.2 aus um einen Treiber zu realisieren und die dazugehörige Anwendung hSps://ezs.kr.hsnr.de/EmbeddedBuch/Download/index.html Beispiel Gerätenummern: Sehen Sie sich das Beispiel 5-5 an. hSps://ezs.kr.hsnr.de/TreiberBuch/Download/index.html

17

Kaus Ruhwinkel | Kernel Programmierung unter Linux