


Deux frameworks de pilotes de périphériques spéciaux dans le noyau Linux : le sous-système misc et le framework de pilotes de reconnaissance de périphériques 3+2+1
Le sous-système misc est un cadre de pilotes de périphériques simple et flexible dans le noyau Linux. Il peut être utilisé pour implémenter certains pilotes de périphériques qui n'appartiennent pas à d'autres sous-systèmes, tels que les périphériques de caractères, les périphériques virtuels, les périphériques hybrides, etc. L'avantage du sous-système misc est qu'il est simple et facile à utiliser. Il ne nécessite pas d'écrire beaucoup de code et ne nécessite que la mise en œuvre de quelques fonctions opérationnelles de base. Cependant, le sous-système misc présente également certaines lacunes, telles que l'incapacité de prendre en charge plusieurs instances de périphériques, l'arborescence des périphériques et le remplacement à chaud. Afin de résoudre ces problèmes, cet article présentera un nouveau cadre de pilote de périphérique : le cadre de pilote de reconnaissance de périphérique 3+2+1, qui est basé sur la combinaison du sous-système divers et du sous-système de plate-forme, et peut réaliser plus de fonctions et de fonctionnalités.
Utilisation de divers
Il existe trois grandes catégories de périphériques sous Linux : les périphériques de caractère, de réseau et de bloc. Chaque périphérique est subdivisé en plusieurs catégories. Par exemple, les périphériques de caractère sont pré-divisés en plusieurs catégories, et le périphérique principal utilisé par ces catégories est marqué. dans le fichier. Numéro de périphérique, mais même ainsi, il y a des dizaines de millions de matériels, et il y a toujours des poissons qui passent entre les mailles du filet. Pour ces périphériques de caractères difficiles à classer, Linux utilise des périphériques « mixtes » pour les décrire de manière uniforme. , et attribuez-leur un appareil principal commun n°10, utilisez uniquement ce numéro d'appareil pour distinguer les appareils, , ces appareils comprennent principalement des générateurs de nombres aléatoires, des écrans LCD, des générateurs d'horloge, etc. De plus, comme de nombreux sous-systèmes qui réencapsulent également cdev, misc créera également automatiquement des fichiers de périphérique, éliminant ainsi le besoin d'utiliser class_create() et device_create() à chaque fois que vous écrivez l'interface cdev.
objets divers fournis dans le noyau :
//include/linux/miscdevice.h 55 struct miscdevice { 56 int minor; 57 const char *name; 58 const struct file_operations *fops; 59 struct list_head list; 60 struct device *parent; 61 struct device *this_device; 62 const char *nodename; 63 umode_t mode; 64 };
fops comme un périphérique de caractère et de lui attribuer un minor Si le mineur utilise la macro MISC_DYNAMIC_MINOR (en fait 255), le noyau attribuera automatiquement un numéro de périphérique mineur, ainsi que les autres noyaux. ont déjà mis en œuvre l'accord. Pour le numéro de périphérique mineur, veuillez vous référer à **"include/linux/miscdevice.h"**. Une fois que tout est prêt, utilisez simplement l'API suivante pour vous inscrire/déconnecter du noyau
178 int misc_register(struct miscdevice * misc) 238 int misc_deregister(struct miscdevice *misc)
analyse de divers
Est-il facile d'utiliser divers ? Mais bien que Sparrow soit petit et bien équipé, c'est précisément grâce à la structure rationalisée de misc que nous pouvons facilement saisir les idées en couches qui y sont incarnées. La méthode de conception de misc se reflète dans de nombreux sous-systèmes qui utilisent cdev comme interface, et. les divisions claires entre eux sont les suivantes : L'idée de couche est l'un des deux piliers des pilotes Linux (l'autre est la séparation).Nous pouvons apprendre des idées de conception et améliorer la qualité de nos chauffeurs. Ensuite, nous analysons brièvement le mécanisme interne de misc.
misc_init
En tant que sous-système de Linux, le sous-système misc terminera le travail de préparation pendant le processus de démarrage de Linux, qui comprend principalementl'initialisation de la structure des données, la création de la classe correspondante, la création, l'initialisation et l'enregistrement de l'objet cdev dans le noyau, etc. . Avec ces fondations, nous pouvons programmer en utilisant les nombreux avantages de divers.
//drivers/char/misc.c 56 static const struct file_operations misc_fops = { 157 .owner = THIS_MODULE, 158 .open = misc_open, 159 .llseek = noop_llseek, 160 }; 268 static int __init misc_init(void) 269 { 272 #ifdef CONFIG_PROC_FS 273 proc_create("misc", 0, NULL, &misc_proc_fops); 274 #endif 275 misc_class = class_create(THIS_MODULE, "misc"); 281 if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) 282 goto fail_printk; 283 misc_class->devnode = misc_devnode; 284 return 0; 292 } 293 subsys_initcall(misc_init);
«
misc_init() –293–>Le sous-système divers sera initialisé lors du démarrage du système
–273–>En fonction de la configuration du système, l'interface /proc peut devoir être fournie
–275–>Créez une classe dans /sysfs nommée misc
–281–>En utilisant le numéro de périphérique majeur statique (10) et l'ensemble de méthodes encapsulées misc_fops, register_chrdev() créera un objet cdev en interne et utilisera ces deux paramètres pour l'initialiser et l'enregistrer dans le noyau. pour tous Le numéro de périphérique du périphérique promiscuité. Pour la relation entre les objets cdev et les numéros de périphérique, voir cdev_map.
–158–>fops utilisé par l'objet cdev de misc. Évidemment, le processus d'appel est le même que celui des périphériques de caractères ordinaires, chrdev_open()->misc_open().
”
misc_register
接下来,老规矩,我们从”XXX_register”开始分析,在Linux内核中,这些”XXX_register”往往就是一个设备对象注册到内核的接口,是研究当相应对象注册进去之后内核动作的最佳入口。
178 int misc_register(struct miscdevice * misc) 179 { 180 dev_t dev; 187 if (misc->minor == MISC_DYNAMIC_MINOR) { 188 int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); 193 misc->minor = DYNAMIC_MINORS - i - 1; 194 set_bit(i, misc_minors); 195 } 206 dev = MKDEV(MISC_MAJOR, misc->minor); 208 misc->this_device = device_create(misc_class, misc->parent, dev, 209 misc, "%s", misc->name); 210 if (IS_ERR(misc->this_device)) { 211 int i = DYNAMIC_MINORS - misc->minor - 1; 212 if (i = 0) 213 clear_bit(i, misc_minors); 214 err = PTR_ERR(misc->this_device); 216 } 222 list_add(&misc->list, &misc_list); 226 }
“
misc_register()
–187–> 如果指定的minor是动态分配,那么进入相关语句块。
–188–> 使dev用位图遍历API-find_first_zero_bit找到最小未用的设备号。
–193–> 得到分配好的次设备号。
–208–> (根据设备号)创建设备文件,使用的是misc_init中创建的misc_class,至此就可以实现misc设备文件的自动创建。就相当与我们在纯粹的cdev驱动中使用class_create()+device_create()创建设备文件。一个设备文件和一个设备号相联系,而misc的所有的设备号都和misc_init创建的cdev对象相联系,所以打开的任何一个misc设备文件首先回调的就是(chrdev_open()->)misc_open()。
–222–> 关键,将这个新分配的misc加入到misc链表中,用于管理所有的misc设备,便于misc_open()提取具体设备的fops。”
misc_open
构建的misc子系统,将设备添加到了该子系统中,接下来我们来看一下应用层程序是如何打开一个misc设备的。由于misc也是一种字符设备,所以其提供的接口也是位于/dev中。但是正如misc的定义,其中的设备五花八门却共用同一个主设备号,这就意味着最终被chrdev_open回调的misc_open一定要具备根据被打开的不同文件为file结构准备不同的操作方法这一能力,即在驱动中实现对子设备的识别,或者称之为”多态”。
112 static int misc_open(struct inode * inode, struct file * file) 113 { 114 int minor = iminor(inode); 115 struct miscdevice *c; 116 int err = -ENODEV; 117 const struct file_operations *new_fops = NULL; 121 list_for_each_entry(c, &misc_list, list) { 122 if (c->minor == minor) { 123 new_fops = fops_get(c->fops); 124 break; 125 } 126 } 144 replace_fops(file, new_fops); 145 if (file->f_op->open) { 146 file->private_data = c; 147 err = file->f_op->open(inode,file); 148 } 152 }
“
misc_open()
–121–>遍历misc设备链表,根据被打开的设备的次设备号找到设备对象。
–123–>存储这个设备对象的操作方法集unique_fops。
–144–>将misc设备具体的操作方法集unique_fops替换到filp中的f_op中,这个位置原来是misc的cdev对象的fops,filp带着这个unique_fops从open()返回,就实现了不同的设备对应不同的操作方法,即面向对象的”多态””
3+2+1多设备识别驱动模型
通过上述对misc机制的分析,我们不难总结出一个支持设备识别的3+2+1驱动模型(3个函数+2个数据结构+1个封装):
- 初始化整个驱动组的**xxx_init()**,通常用模块加载函数或总线的probe函数实现;
- 用于注册一个子驱动的**xxx_register()**,需要EXPORT到符号表;
- 能够根据传入的inode识别具体的设备并将其操作方法集放到filp中的**xxx_open()**。
+
- 用于存储每一个驱动对象的通用链表或数组+priv_data
- 用于存储子设备号的位图。
+
- 将所有的不同的设备用一个统一的结构进行封装
至此,我们就可以写一写这个3+2+1驱动模型的模板。
1个封装
struct multidevice{ struct list_head head; int minor; struct file_operations* fops; void *priv; //私有数据,供read/write等接口识别的信息,以及其他数据都放这里 };
2个数据结构
struct list_head multi_dev_list; unsigned int minors_map; //根据设备号数目的不同选数据类型or数组
3个函数
int major,baseminor = 0,max_dev = sizeof(minors_map)*8; #define DEV_NAME "multi_device" struct class *cls; xxx_open(struct inode *inode,struct file *file){ int minor = iminor(inode); struct multidevice *dp; const struct file_operations *new_fops = NULL; list_for_each_entry(dp, &multi_dev_list, head) { if (dp->minor == minor) { new_fops = fops_get(dp->fops); break; } } replace_fops(file, new_fops); if (file->f_op->open) { file->private_data = dp file->f_op->open(inode,file); } } xxx_init(void){ dev_t devno, INIT_LIST_HEAD(&multi_dev_list); init_map(&minors_map); struct cdev *multi_cdev = cdev_alloc(); cdev_init(multi_cdev, multi_fops); alloc_chrdev_region(&devno, baseminor, count,DEV_NAME); major = MAJOR(devno); cdev_add(multi_cdev , devno, count); cls = class_create(THIS_MODULE, DEV_NAME); } /*---------------下面是给待加驱动用的----------------------*/ xxx_register(struct *multidevice dev){ dev_t dev; if (dev->minor == MISC_DYNAMIC_MINOR) { int i = find_first_zero_bit(minors_map, DYNAMIC_MINORS); dev->minor = DYNAMIC_MINORS - i - 1; set_bit(i, minors_map); } dev_t pri_devno = MKDEV(major, dev->minor); device_create(multi_class, NULL, pri_devno, "%s", misc->name); list_add(dev->head, &multi_dev_list); } EXPORT_SYMBOL(xxx_register)
通过本文,我们了解了misc子系统和3+2+1设备识别驱动框架的原理和方法,它们可以用来实现一些特殊的设备驱动,如识别设备,虚拟设备,混合设备等。我们应该根据实际需求选择合适的框架,并遵循一些基本原则,如使用正确的注册和注销函数,使用正确的文件操作结构体,使用正确的设备树节点等。misc子系统和3+2+1设备识别驱动框架是Linux内核中两个有用而灵活的设备驱动框架,它们可以提升设备驱动的兼容性和可扩展性,也可以提升开发者的效率和质量。希望本文能够对你有所帮助和启发。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Étapes pour démarrer Nginx dans Linux: Vérifiez si Nginx est installé. Utilisez SystemCTL Start Nginx pour démarrer le service NGINX. Utilisez SystemCTL Activer Nginx pour activer le démarrage automatique de Nginx au démarrage du système. Utilisez SystemCTL Status Nginx pour vérifier que le démarrage est réussi. Visitez http: // localhost dans un navigateur Web pour afficher la page de bienvenue par défaut.

Comment confirmer si Nginx est démarré: 1. Utilisez la ligne de commande: SystemCTl Status Nginx (Linux / Unix), netStat -ano | Findstr 80 (Windows); 2. Vérifiez si le port 80 est ouvert; 3. Vérifiez le message de démarrage NGINX dans le journal système; 4. Utilisez des outils tiers, tels que Nagios, Zabbix et Icinga.

Le serveur n'a pas l'autorisation d'accéder à la ressource demandée, ce qui donne une erreur NGINX 403. Les solutions incluent: vérifier les autorisations de fichiers. Vérifiez la configuration .htaccess. Vérifiez la configuration de Nginx. Configurez les autorisations Selinux. Vérifiez les règles du pare-feu. Dépanner d'autres causes telles que les problèmes de navigateur, les défaillances du serveur ou d'autres erreurs possibles.

Les principales différences entre Centos et Ubuntu sont: l'origine (Centos provient de Red Hat, pour les entreprises; Ubuntu provient de Debian, pour les particuliers), la gestion des packages (Centos utilise Yum, se concentrant sur la stabilité; Ubuntu utilise APT, pour une fréquence de mise à jour élevée), le cycle de support (CentOS fournit 10 ans de soutien, Ubuntu fournit un large soutien de LT tutoriels et documents), utilisations (Centos est biaisé vers les serveurs, Ubuntu convient aux serveurs et aux ordinateurs de bureau), d'autres différences incluent la simplicité de l'installation (Centos est mince)

Docker utilise les fonctionnalités du noyau Linux pour fournir un environnement de fonctionnement d'application efficace et isolé. Son principe de travail est le suivant: 1. Le miroir est utilisé comme modèle en lecture seule, qui contient tout ce dont vous avez besoin pour exécuter l'application; 2. Le Système de fichiers Union (UnionFS) empile plusieurs systèmes de fichiers, ne stockant que les différences, l'économie d'espace et l'accélération; 3. Le démon gère les miroirs et les conteneurs, et le client les utilise pour l'interaction; 4. Les espaces de noms et les CGROUP implémentent l'isolement des conteneurs et les limitations de ressources; 5. Modes de réseau multiples prennent en charge l'interconnexion du conteneur. Ce n'est qu'en comprenant ces concepts principaux que vous pouvez mieux utiliser Docker.

Centos sera fermé en 2024 parce que sa distribution en amont, Rhel 8, a été fermée. Cette fermeture affectera le système CentOS 8, l'empêchant de continuer à recevoir des mises à jour. Les utilisateurs doivent planifier la migration et les options recommandées incluent CentOS Stream, Almalinux et Rocky Linux pour garder le système en sécurité et stable.

Étapes d'installation de CentOS: Téléchargez l'image ISO et Burn Bootable Media; démarrer et sélectionner la source d'installation; sélectionnez la langue et la disposition du clavier; configurer le réseau; partitionner le disque dur; définir l'horloge système; créer l'utilisateur racine; sélectionnez le progiciel; démarrer l'installation; Redémarrez et démarrez à partir du disque dur une fois l'installation terminée.

Comment utiliser Docker Desktop? Docker Desktop est un outil pour exécuter des conteneurs Docker sur les machines locales. Les étapes à utiliser incluent: 1. Installer Docker Desktop; 2. Démarrer Docker Desktop; 3. Créer une image Docker (à l'aide de DockerFile); 4. Build Docker Image (en utilisant Docker Build); 5. Exécuter Docker Container (à l'aide de Docker Run).
