Description
Laissez-nous commencer la discussion avec le pilote de personnage dans Linux. Le noyau catégorise les pilotes en trois catégories:
Moteurs de personnage - Ce sont les pilotes qui n'ont pas trop de données pour gérer. Peu d'exemples de pilotes de caractère sont le pilote à écran tactile, le pilote UART, etc. Ce sont tous les pilotes de caractère car le transfert de données se fait via le caractère par caractère.
Bloquer les conducteurs - Ce sont les pilotes qui traitent de trop de données. Le transfert de données est effectué en bloc par bloc car trop de données doivent être transférées. L'exemple de pilotes de blocs est SATA, NVME, etc.
Pilotes de réseau - Ce sont les pilotes qui fonctionnent dans le groupe de réseaux de réseaux. Ici, le transfert de données est effectué sous forme de paquets de données. Les conducteurs sans fil comme Atheros sont dans cette catégorie.
Dans cette discussion, nous nous concentrerons uniquement sur le pilote de personnage.
Par exemple, nous prendrons les opérations de lecture / écriture simples pour comprendre le pilote de personnage de base. Généralement, tout pilote de périphérique a ces deux opérations minimales. L'opération supplémentaire pourrait être ouverte, proche, ioctl, etc. Dans notre exemple, notre pilote a la mémoire dans l'espace du noyau. Cette mémoire est allouée par le pilote de périphérique et peut être considérée comme la mémoire de l'appareil car aucun composant matériel n'est impliqué. Le pilote crée l'interface de l'appareil dans le répertoire / dev peut être utilisé par les programmes d'espace utilisateur pour accéder au pilote et effectuer les opérations prises en charge par le pilote. Pour le programme Userspace, ces opérations sont comme toutes les autres opérations de fichiers. Le programme d'espace utilisateur doit ouvrir le fichier de périphérique pour obtenir l'instance de l'appareil. Si l'utilisateur souhaite effectuer l'opération de lecture, l'appel du système de lecture peut être utilisé pour le faire. De même, si l'utilisateur souhaite effectuer l'opération d'écriture, l'appel du système d'écriture peut être utilisé pour réaliser l'opération d'écriture.
Conducteur de personnage
Considérons pour implémenter le pilote de caractère avec les opérations de données de lecture / écriture.
Nous commençons par prendre l'instance des données de l'appareil. Dans notre cas, c'est "struct cdrv_device_data".
Si nous voyons les champs de cette structure, nous avons CDEV, le tampon de périphérique, la taille du tampon, l'instance de classe et l'objet de périphérique. Ce sont les champs minimaux où nous devons implémenter le pilote de caractère. Cela dépend de l'implémentateur des champs supplémentaires qu'il veut ajouter pour améliorer le fonctionnement du conducteur. Ici, nous essayons d'atteindre le fonctionnement minimum.
Ensuite, nous devons créer l'objet de la structure de données de l'appareil. Nous utilisons l'instruction pour allouer la mémoire de manière statique.
struct cdrv_device_data char_device [cdrv_max_minors];
Cette mémoire peut également être allouée dynamiquement avec «Kmalloc». Gardons la mise en œuvre aussi simple que possible.
Nous devons prendre la mise en œuvre des fonctions de lecture et d'écriture. Le prototype de ces deux fonctions est défini par le cadre du pilote de périphérique de Linux. La mise en œuvre de ces fonctions doit être définie par l'utilisateur. Dans notre cas, nous avons examiné ce qui suit:
Lire: L'opération pour obtenir les données de la mémoire du pilote à l'espace utilisateur.
STATIC SSIZE_T CDRV_READ (fichier struct * Fichier, char __User * user_buffer, size_t size, loff_t * offset);
Écrire: l'opération pour stocker les données à la mémoire du pilote à partir de l'espace utilisateur.
STATIC SSIZE_T CDRV_WRITE (fichier struct * Fichier, const char __User * user_buffer, size_t size, loff_t * offset);
Les deux opérations, lecture et écriture, doivent être enregistrées dans le cadre de Struct File_Operations CDRV_FOPS. Ceux-ci sont enregistrés dans le cadre du pilote de périphérique Linux dans le pilote init_cdrv () du pilote. À l'intérieur de la fonction init_cdrv (), toutes les tâches de configuration sont effectuées. Peu de tâches sont les suivantes:
L'exemple de code complet pour le pilote de périphérique de caractères de base est le suivant:
#inclureNous créons un échantillon de MakeFile pour compiler le pilote de base et l'application de test. Notre code de pilote est présent dans CRDV.C et le code d'application de test est présent dans CDRV_App.c.
OBJ-M + = CDRV.oUne fois l'émission réalisée au Makefile, nous devrions obtenir les journaux suivants. Nous obtenons également le CDRV.ko et exécutable (cdrv_app) pour notre application de test:
root @ haxv-srathore-2: / home / cienauser / kernel_articles # faireVoici l'exemple de code de l'application de test. Ce code implémente l'application de test qui ouvre le fichier de périphérique créé par le pilote CDRV et y écrit les «données de test». Ensuite, il lit les données du pilote et les imprime après avoir lu les données à imprimer sous forme de «données de test».
#inclureUne fois que nous avons toutes les choses en place, nous pouvons utiliser la commande suivante pour insérer le pilote de caractère de base au noyau Linux:
root @ haxv-srathore-2: / home / cienauser / kernel_articles # insmod cdrv.koAprès avoir inséré le module, nous obtenons les messages suivants avec DMESG et obtenons le fichier de périphérique créé dans / dev / dev / cdrv_dev:
root @ haxv-srathore-2: / home / cienauser / kernel_articles # dmesgMaintenant, exécutez l'application de test avec la commande suivante dans le shell Linux. Le message final imprime les données de lecture du pilote, ce qui est exactement la même que ce que nous avons écrit dans l'opération d'écriture:
root @ haxv-srathore-2: / home / cienauser / kernel_articles # ./ cdrv_appNous avons quelques impressions supplémentaires dans le chemin d'écriture et de lecture qui peut être vu à l'aide de la commande DMESG. Lorsque nous émettez la commande DMESG, nous obtenons la sortie suivante:
root @ haxv-srathore-2: / home / cienauser / kernel_articles # dmesgConclusion
Nous avons parcouru le pilote de caractère de base qui implémente les opérations de base de l'écriture et de la lecture. Nous avons également discuté de l'échantillon MakeFile pour compiler le module avec l'application de test. L'application de test a été écrite et discutée pour effectuer les opérations d'écriture et de lecture de l'espace utilisateur. Nous avons également démontré la compilation et l'exécution du module et de l'application de test avec des journaux. L'application de test écrit quelques octets de données de test, puis les lit en arrière. L'utilisateur peut comparer les deux données pour confirmer le bon fonctionnement du pilote et de l'application de test.