Comment créer un pilote de périphérique Linux intégré (7)

7ème: Interface pour procfs

À propos de cette série

Article HowTo pour développer des pilotes de périphériques Linux embarqués en tant que modules de noyau. Tout le contenu de cet article peut être exécuté sur Raspberry Pi.

Le code source complet qui apparaît dans cet article

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

Contenu de cette époque

Jusqu'à la dernière fois, en plus des appels système de base (ouvrir, fermer, lire, écrire), nous avons implémenté ioctl. Cela couvre la plupart des interfaces minimales requises pour un pilote de périphérique (skip select / poll).

En fait, si vous développez pour contrôler un périphérique (par exemple, un capteur ou un actionneur), vous souhaiterez peut-être modifier ou obtenir des paramètres de débogage. Ce serait très pratique de pouvoir le faire depuis le shell. Ceci peut être réalisé en lisant / écrivant dans des fichiers dans le système de fichiers proc (procfs). Par exemple, supposons que vous créez le fichier suivant.

Vous pouvez vérifier la valeur du capteur en lisant la valeur de / proc / mydevice_sensor0 (par exemple, cat), ou vous pouvez contrôler le moteur en écrivant la valeur de / proc / mydevice_motor0 (par exemple, ʻecho). ). Fondamentalement, c'est la même chose que la lecture / écriture du pilote de périphérique qui a été créé jusqu'à présent. Cependant, jusqu'à présent, il était en lecture / écriture pour le fichier de périphérique (/ dev / mydevice`). Cette fois, nous le ferons pour le fichier procfs. Vous pouvez en fabriquer autant que vous le souhaitez. Ceci est utile lorsque vous avez un seul appareil et de nombreux paramètres que vous souhaitez vérifier.

Remarque (note supplémentaire)

Dans les commentaires, @rarul a souligné. Il semble qu'il soit recommandé d'utiliser procfs uniquement pour organiser les informations de processus et les débogages à des fins de débogage, comme mentionné ci-dessus. Je décrirai les debugfs la prochaine fois. Il ne devrait pas être utilisé pour le débogage, mais je pense que c'est un bon moyen de créer des procfs, je vais donc laisser cet article tel quel.

Implémentation de l'interface pour procfs

Pour créer une interface pour procfs, enregistrez simplement le nom du fichier et la fonction que vous souhaitez appeler en lecture / écriture avec la fonction proc_create où le pilote est chargé (insmod). Lors de l'enregistrement, définissez la fonction de gestion de lecture / écriture dans la table struct file_operations. En fait, il s'agit exactement de la même procédure que l'enregistrement d'un gestionnaire pour un pilote de périphérique normal. La seule différence est la fonction utilisée. Utilisez la fonction remove_proc_entry pour le supprimer.

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>

/***Informations sur cet appareil***/
MODULE_LICENSE("Dual BSD/GPL");
#define DRIVER_NAME "MyDevice"				/* /proc/Nom de l'appareil affiché sur les appareils, etc.*/
#define PROC_NAME "MyDevice_test"			/* /Le nom de procfs à créer dans proc*/

/*variables de test procfs*/
static char proc_test_string[16];
static int  flag_read = 0;

/* /proc/MyDevice_Fonction appelée lors de l'accès au test*/
static int mydevice_proc_open(struct inode *inode, struct file *file)
{
	printk("mydevice_proc_open\n");
	flag_read = 0;
	return 0;
}

/* /proc/MyDevice_Fonction appelée lors de la lecture du test*/
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_Fonction appelée lors de l'écriture du test*/
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;	
}

/*Table des gestionnaires pour procfs*/
static struct file_operations mydevice_proc_fops = {
	.owner = THIS_MODULE,
	.open  = mydevice_proc_open,
	.read  = mydevice_proc_read,
	.write = mydevice_proc_write,
};

/*Route(insmod)Fonctions parfois appelées*/
static int mydevice_init(void)
{
	printk("mydevice_init\n");

	struct proc_dir_entry *entry;
	/*Créer des 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;
}

/*Décharger(rmmod)Fonctions parfois appelées*/
static void mydevice_exit(void)
{
	printk("mydevice_exit\n");

	/*Débarrassez-vous de procfs*/
	remove_proc_entry(PROC_NAME, NULL);
}

module_init(mydevice_init);
module_exit(mydevice_exit);

Créons un fichier appelé / proc / MyDevice_test. Le traitement lors de la lecture de ce fichier (mydevice_proc_read), le traitement lors de l'écriture ( mydevice_proc_write) et le traitement lors de l'ouverture (mydevice_proc_open) sont implémentés. Le processus à l'ouverture est toujours appelé à chaque fois que vous lisez ou écrivez à partir du shell. Je pense que ça va sans ça. En fait, close est omis.

mydevice_proc_write contient la chaîne définie par l'utilisateur dans une variable statique interne ( proc_test_string). Renvoie le contenu contenu par mydevice_proc_read. Je veux que vous l'appeliez une seule fois par lecture (cat), donc je gère le drapeau et l'efface au moment de l'ouverture. Je pense qu'il existe une meilleure façon de procéder.

Lors du chargement du module, utilisez la fonction proc_create pour créer le fichier / proc / MyDevice_test. S_IRUGO | S_IWUGO est identique à 0666, donnant l'accès RW à tous les utilisateurs.

Essayez de lire et d'écrire des paramètres via procfs

Construisez et chargez avec la commande suivante.

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

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

Après le chargement, / proc / MyDevice_test sera créé. Pour cela, écrivez la valeur avec echo. Après cela, lorsque vous le lisez avec cat, la valeur que vous avez écrite précédemment est sortie.

Remarque

Le contenu de cet article est en ligne avec le contenu de "Linux Device Driver Programming (Yutaka Hirata)". Le livre utilisait create_proc_entry pour s'enregistrer dans le système de fichiers proc. Cependant, il est désormais obsolète. Cet article utilise à la place proc_create.

Remarque 2: sysfs

Comme vous l'avez souligné dans les commentaires, procfs échange initialement des informations sur le processus. Comme mentionné dans le prochain article, les debugfs échangeront des informations pour le débogage.

En dehors de ceux-ci, il existe un mécanisme d'échange de paramètres avec les modules. Vous pouvez vérifier les informations et les paramètres du module en tant que sysfs qui peuvent être placés sous le répertoire / sys. Cela ressemble à procfs, mais procfs est l'ancienne méthode, et comme je l'ai écrit dans cet article, les développeurs Devadora sont libres de l'ajouter. En conséquence, il est devenu chaotique. sysfs doit être enregistré de la manière correcte. Et chaque fichier est organisé et géré par répertoire.

Il existe différentes méthodes, mais si vous voulez juste afficher les paramètres, vous pouvez le faire avec une macro d'aide appelée module_param (). Cela vous permet de définir des paramètres et de lire les valeurs des paramètres (variables) lors du chargement d'un module. Cependant, il semble que les paramètres ne puissent pas être modifiés après le chargement du noyau.

Je vais vraiment l'utiliser. Tout ce que vous avez à faire est de déclarer la variable et de lire module_param (). Un exemple d'utilisation de la variable «param1» comme paramètre est présenté ci-dessous.

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

Vous pouvez vérifier la valeur de param1 en lisant / sys / module / MyDeviceModule / parameters / param1. Vous pouvez également spécifier une valeur pendant insmod.

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

Comment créer un pilote de périphérique Linux intégré (11)
Comment créer un pilote de périphérique Linux intégré (8)
Comment créer un pilote de périphérique Linux intégré (4)
Comment créer un pilote de périphérique Linux intégré (7)
Comment créer un pilote de périphérique Linux intégré (2)
Comment créer un pilote de périphérique Linux intégré (3)
Comment créer un pilote de périphérique Linux intégré (6)
Comment créer un pilote de périphérique Linux intégré (5)
Comment créer un pilote de périphérique Linux intégré (10)
Comment créer un pilote de périphérique Linux intégré (9)
Comment créer un pilote de périphérique Linux intégré (12) (Terminé)
Comment faire reconnaître Yubico Yubikey par Manjaro Linux
Comment créer un outil CLI interactif avec Golang
Comment créer un serveur HTTPS avec Go / Gin
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64 bits Partie 2-
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64-bit edition -
Comment créer un package Python (écrit pour un stagiaire)
Comment créer un fichier ISO (image CD) sous Linux
Comment faire une traduction japonais-anglais
Comment créer un bot slack
Comment installer VMware-Tools sur Linux
Comment créer un robot - Avancé
Comment créer une fonction récursive
Comment installer MBDyn (Linux Ubuntu)
[Blender] Comment créer un plug-in Blender
[Blender] Comment rendre les scripts Blender multilingues
Comment créer un robot - Basic
Comment créer un pilote de langage MongoDB C
Comment vérifier la version du système d'exploitation Linux
Comment transformer une chaîne en tableau ou un tableau en chaîne en Python
Comment obtenir le pilote d'imprimante pour Oki Mac sous Linux
Comment rendre les caractères de Word Cloud monochromatiques
Comment rendre le sélénium aussi léger que possible
[Linux] Comment subdiviser des fichiers et des dossiers
Comment créer un bot LINE à intelligence artificielle avec l'API de messagerie Flask + LINE
Comment installer aws-session-manager-plugin sur Manajro Linux
[Python] Comment rendre une classe itérable
python3 Comment installer un module externe
Comment créer un environnement NVIDIA Docker
Comment convertir Python en fichier exe
[Linux] Comment utiliser la commande echo
Comment mettre à jour PHP sur Amazon Linux 2
Comment afficher des pictogrammes sur Manjaro Linux
Comment installer des packages sur Alpine Linux
[Cocos2d-x] Comment créer une liaison de script (partie 2)
Comment faire fonctionner Linux depuis la console
Comment installer le sous-système Windows pour Linux
Comment mettre hors tension de Linux sur Ultra96-V2
Comment mettre à jour la sécurité sur CentOS Linux 8
Je veux faire un programme d'automatisation!
Comment installer php7.4 sur Linux (Ubuntu)
Comment créer une clé USB à démarrage multiple (compatible Windows 10)
Comment créer un indicateur personnalisé Backtrader
Comment créer un plan de site Pelican