So erstellen Sie einen eingebetteten Linux-Gerätetreiber (7)

7. Schnittstelle für procfs

Über diese Serie

HowTo-Artikel zum Entwickeln eingebetteter Linux-Gerätetreiber als Kernelmodule. Der gesamte Inhalt dieses Artikels kann auf Raspberry Pi ausgeführt werden.

Der gesamte Quellcode, der in diesem Artikel angezeigt wird

https://github.com/take-iwiw/DeviceDriverLesson/tree/master/07_01

Inhalt dieser Zeit

Bis zum letzten Mal haben wir zusätzlich zu den grundlegenden Systemaufrufen (Öffnen, Schließen, Lesen, Schreiben) ioctl implementiert. Dies deckt die meisten der minimal erforderlichen Schnittstellen für einen Gerätetreiber ab (Auswahl / Abfrage überspringen).

Wenn Sie ein Gerät (z. B. einen Sensor oder Aktor) steuern möchten, möchten Sie möglicherweise Parameter für das Debuggen ändern oder abrufen. Es wäre sehr praktisch, dies von der Shell aus tun zu können. Dies kann durch Lesen / Schreiben in Dateien im proc-Dateisystem (procfs) erreicht werden. Angenommen, Sie erstellen die folgende Datei.

Sie können den Sensorwert überprüfen, indem Sie den Wert von "/ proc / mydevice_sensor0" (z. B. "cat") lesen, oder Sie können den Motor steuern, indem Sie den Wert von "/ proc / mydevice_motor0" (z. B. "echo") schreiben. ). Grundsätzlich entspricht dies dem Lesen / Schreiben des bisher erstellten Gerätetreibers. Bisher wurde es jedoch für die Gerätedatei (/ dev / mydevice) gelesen / geschrieben. Dieses Mal machen wir das für die procfs-Datei. Sie können so viele machen, wie Sie möchten. Dies ist nützlich, wenn Sie ein einzelnes Gerät und viele Parameter haben, die Sie überprüfen möchten.

Hinweis (zusätzlicher Hinweis)

In den Kommentaren wies @rarul darauf hin. Es wird empfohlen, procfs nur zum Anordnen von Prozessinformationen und Debugfs für Debugging-Zwecke zu verwenden, wie oben erwähnt. Ich werde das nächste Mal Debugfs beschreiben. Es sollte nicht zum Debuggen verwendet werden, aber ich denke, es ist eine gute Möglichkeit, procfs zu erstellen, also lasse ich diesen Artikel so wie er ist.

Implementierung der Schnittstelle für procfs

Um eine Schnittstelle für procfs zu erstellen, registrieren Sie einfach den Dateinamen und die Funktion, die Sie beim Lesen / Schreiben aufrufen möchten, mit der Funktion "proc_create", in die der Treiber geladen wird (insmod). Stellen Sie bei der Registrierung die Lese- / Schreibhandlerfunktion in der Tabelle struct file_operations ein. Tatsächlich ist dies genau das gleiche Verfahren wie das Registrieren eines Handlers für einen normalen Gerätetreiber. Der einzige Unterschied ist die verwendete Funktion. Verwenden Sie die Funktion remove_proc_entry, um es zu entfernen.

myDeviceDriver.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

/***Informationen zu diesem Gerät***/
MODULE_LICENSE("Dual BSD/GPL");
#define DRIVER_NAME "MyDevice"				/* /proc/Gerätename in Geräten usw. angezeigt.*/
#define PROC_NAME "MyDevice_test"			/* /Der Name von procfs, die in proc erstellt werden sollen*/

/*procfs Testvariablen*/
static char proc_test_string[16];
static int  flag_read = 0;

/* /proc/MyDevice_Funktion beim Zugriff auf Test aufgerufen*/
static int mydevice_proc_open(struct inode *inode, struct file *file)
{
	printk("mydevice_proc_open\n");
	flag_read = 0;
	return 0;
}

/* /proc/MyDevice_Funktion beim Lesen des Tests aufgerufen*/
static ssize_t mydevice_proc_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	printk("mydevice_proc_read\n");

	if (flag_read == 0) {
		int len;
		len = sprintf(buf, "%s\n", proc_test_string);
		flag_read = 1;
		return len;
	} else {
		return 0;
	}
}

/* /proc/MyDevice_Funktion, die beim Schreiben des Tests aufgerufen wird*/
static ssize_t mydevice_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	printk("mydevice_proc_write\n");

	if (count > sizeof(proc_test_string)) count = sizeof(proc_test_string) - 1;
	if (copy_from_user(proc_test_string, buf, count)) {
		return -EFAULT;
	}
	proc_test_string[count] = '\0';
	return count;	
}

/*Handlertabelle für procfs*/
static struct file_operations mydevice_proc_fops = {
	.owner = THIS_MODULE,
	.open  = mydevice_proc_open,
	.read  = mydevice_proc_read,
	.write = mydevice_proc_write,
};

/*Straße(insmod)Funktionen, die manchmal aufgerufen werden*/
static int mydevice_init(void)
{
	printk("mydevice_init\n");

	struct proc_dir_entry *entry;
	/*Erstellen Sie procfs*/
	entry = proc_create(PROC_NAME, S_IRUGO | S_IWUGO, NULL, &mydevice_proc_fops);
	if (entry == NULL) {
		printk(KERN_ERR "proc_create\n");
		return -ENOMEM;
	}

	return 0;
}

/*Entladen(rmmod)Funktionen, die manchmal aufgerufen werden*/
static void mydevice_exit(void)
{
	printk("mydevice_exit\n");

	/*Procfs loswerden*/
	remove_proc_entry(PROC_NAME, NULL);
}

module_init(mydevice_init);
module_exit(mydevice_exit);

Erstellen wir eine Datei mit dem Namen "/ proc / MyDevice_test". Die Verarbeitung beim Lesen dieser Datei (mydevice_proc_read), die Verarbeitung beim Schreiben ( mydevice_proc_write) und die Verarbeitung beim Öffnen (mydevice_proc_open) sind implementiert. Der Prozess beim Öffnen wird immer jedes Mal aufgerufen, wenn Sie aus der Shell lesen oder schreiben. Ich denke, es ist okay ohne es. In der Tat wird Schließen weggelassen.

mydevice_proc_write enthält die benutzerdefinierte Zeichenfolge in einer internen statischen Variablen ( proc_test_string). Gibt den Inhalt von mydevice_proc_read zurück. Ich möchte, dass Sie es nur einmal pro Lesung aufrufen (cat), also verwalte ich die Flagge und lösche sie zum Zeitpunkt des Öffnens. Ich denke, es gibt einen besseren Weg, dies zu tun.

Verwenden Sie beim Laden des Moduls die Funktion proc_create, um die Datei / proc / MyDevice_test zu erstellen. S_IRUGO | S_IWUGO ist dasselbe wie 0666 und gewährt allen Benutzern RW-Zugriff.

Versuchen Sie, Parameter über procfs zu lesen und zu schreiben

Erstellen und laden Sie mit dem folgenden Befehl.

make 
sudo insmod  MyDeviceModule.ko
ls /proc/MyDevice_test
/proc/MyDevice_test

echo "abc" > /proc/MyDevice_test
cat /proc/MyDevice_test
abc

Nach dem Laden wird / proc / MyDevice_test erstellt. Schreiben Sie dazu den Wert mit echo. Wenn Sie es danach mit cat lesen, wird der Wert ausgegeben, den Sie zuvor geschrieben haben.

Hinweis

Der Inhalt dieses Artikels entspricht dem Inhalt von "Linux Device Driver Programming (Yutaka Hirata)". Das Buch verwendete "create_proc_entry", um sich beim proc-Dateisystem zu registrieren. Es ist jedoch jetzt veraltet. Dieser Artikel verwendet stattdessen "proc_create".

Anmerkung 2: sysfs

Wie Sie in den Kommentaren betont haben, tauscht procfs ursprünglich Informationen über den Prozess aus. Wie wir im nächsten Artikel sehen werden, tauscht debugfs Informationen zum Debuggen aus.

Abgesehen von diesen gibt es einen Mechanismus zum Austausch von Parametern mit Modulen. Sie können die Modulinformationen und -parameter als sysfs überprüfen, die im Verzeichnis / sys abgelegt werden können. Dies sieht genauso aus wie procfs, aber procfs ist der alte Weg, und wie ich in diesem Artikel geschrieben habe, können Devadora-Entwickler es hinzufügen. Infolgedessen ist es chaotisch geworden. sysfs muss korrekt registriert sein. Und jede Datei ist nach Verzeichnissen organisiert und verwaltet.

Es gibt verschiedene Methoden, aber wenn Sie nur die Parameter anzeigen möchten, können Sie dies mit einem Hilfsmakro namens "module_param ()" tun. Auf diese Weise können Sie beim Laden eines Moduls Parameter einstellen und die Werte von Parametern (Variablen) lesen. Es scheint jedoch, dass die Parameter nach dem Laden des Kernels nicht geändert werden können.

Ich werde es tatsächlich benutzen. Sie müssen lediglich die Variable deklarieren und module_param () lesen. Ein Beispiel für die Verwendung der Variablen param1 als Parameter ist unten dargestellt.

static int param1 = 10;
module_param(param1, int, S_IRUGO);

Sie können den Wert von param1 überprüfen, indem Sie / sys / module / MyDeviceModule / parameters / param1 lesen. Sie können während insmod auch einen Wert angeben.

sudo insmod MyDeviceModule.ko
cat /sys/module/MyDeviceModule/parameters/param1
  10

sudo rmmod MyDeviceModule
sudo insmod MyDeviceModule.ko param1=20
cat /sys/module/MyDeviceModule/parameters/param1
  20

Recommended Posts

So erstellen Sie einen eingebetteten Linux-Gerätetreiber (11)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (8)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (4)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (7)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (2)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (3)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (6)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (5)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (10)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (9)
So erstellen Sie einen eingebetteten Linux-Gerätetreiber (12) (vollständig)
Wie man Yubico Yubikey von Manjaro Linux erkennt
So erstellen Sie ein interaktives CLI-Tool mit Golang
So erstellen Sie einen HTTPS-Server mit Go / Gin
So erstellen Sie ein Hacking-Labor - Kali Linux (2020.1) VirtualBox 64-Bit Teil 2-
So erstellen Sie ein Hacking-Labor - Kali Linux (2020.1) VirtualBox 64-Bit-Edition -
Wie erstelle ich ein Python-Paket (geschrieben für Praktikanten)
So erstellen Sie eine ISO-Datei (CD-Image) unter Linux
Wie erstelle ich eine japanisch-englische Übersetzung?
Wie man einen lockeren Bot macht
So installieren Sie VMware-Tools unter Linux
Wie erstelle ich einen Crawler?
So erstellen Sie eine rekursive Funktion
So installieren Sie MBDyn (Linux Ubuntu)
[Blender] So erstellen Sie ein Blender-Plug-In
[Blender] So erstellen Sie Blender-Skripte mehrsprachig
Wie erstelle ich einen Crawler?
So erstellen Sie den MongoDB C-Sprachtreiber
So überprüfen Sie die Linux-Betriebssystemversion
So machen Sie einen String in Python zu einem Array oder ein Array zu einem String
So bringen Sie den Druckertreiber für Oki Mac in Linux
So machen Sie Word Cloud-Zeichen monochromatisch
Wie man Selen so leicht wie möglich macht
[Linux] Unterteilen von Dateien und Ordnern
So erstellen Sie einen LINE-Bot mit künstlicher Intelligenz mit der Flask + LINE Messaging-API
So installieren Sie das aws-session-manager-Plugin unter Manajro Linux
[Python] Wie man eine Klasse iterierbar macht
python3 So installieren Sie ein externes Modul
So erstellen Sie eine NVIDIA Docker-Umgebung
So konvertieren Sie Python in eine exe-Datei
[Linux] Verwendung des Befehls echo
So aktualisieren Sie PHP unter Amazon Linux 2
So zeigen Sie Piktogramme unter Manjaro Linux an
So installieren Sie Pakete unter Alpine Linux
[Cocos2d-x] So erstellen Sie eine Skriptbindung (Teil 2)
So bedienen Sie Linux von der Konsole aus
So installieren Sie das Windows-Subsystem für Linux
So schalten Sie Linux unter Ultra96-V2 aus
So aktualisieren Sie die Sicherheit unter CentOS Linux 8
Ich möchte ein Automatisierungsprogramm erstellen!
Wie installiere ich php7.4 unter Linux (Ubuntu)
So machen Sie Multi-Boot-USB (Windows 10-kompatibel)
So erstellen Sie einen benutzerdefinierten Backtrader-Indikator
Wie erstelle ich eine Pelican Site Map?