Table des matières
模板" >模板
IO多路复用的实现" >IO多路复用的实现
模板" >模板
其他API" >其他API
Maison Tutoriel système Linux Explication détaillée de la technologie du pilote Linux (5)_Blocage de périphérique/lecture et écriture non bloquantes

Explication détaillée de la technologie du pilote Linux (5)_Blocage de périphérique/lecture et écriture non bloquantes

Feb 15, 2024 pm 04:00 PM
linux linux教程 linux系统 linux命令 shell脚本 typedef overflow Linux embarqué Débuter avec Linux apprentissage Linux

Dans le processus d'écriture des pilotes Linux, le blocage/lecture et l'écriture non bloquantes des périphériques est une technologie très importante. Il peut assurer une transmission de données et un traitement des événements efficaces, améliorant ainsi les performances du système et la vitesse de réponse. Dans cet article, nous approfondirons la technologie des pilotes Linux (5)_Les principes de mise en œuvre et les technologies associées de blocage/non-blocage des périphériques en lecture et en écriture.

详解Linux驱动技术(五) _设备阻塞/非阻塞读写

La file d'attente est une structure de données très importante dans le noyau pour la planification des processus. Sa tâche est de maintenir une liste chaînée est un PCB (Process Control Block). la file d'attente Tous les processus sont programmés pour dormir jusqu'à ce qu'une certaine condition de réveil se produise. J'ai déjà discuté de l'utilisation des E/S bloquantes et des E/S non bloquantes au niveau de la couche application dans l'article Multiplexage des E/S Linux. Cet article explique principalement comment implémenter la lecture et l'écriture bloquantes et non bloquantes des E/S du périphérique dans le pilote. Évidemment, le mécanisme de file d'attente est nécessaire pour mettre en œuvre ce mécanisme lié au blocage. Le code source du noyau de cet article utilise la version 3.14.0

Mise en place d'un dispositif bloquant les IO

Lorsque nous lisons et écrivons les IO du fichier de périphérique, l'interface correspondante dans le pilote sera éventuellement rappelée, et ces

interfaces apparaîtront également dans l'espace de processus (noyau) du processus de lecture et d'écriture du périphérique. les conditions ne sont pas remplies, la fonction d'interface fera entrer le processus en état de veille, même si le processus utilisateur de lecture et d'écriture de l'appareil entre en veille, c'est ce que nous disons souvent qu'il est bloqué. En un mot, l'essence du blocage des fichiers de périphérique en lecture et en écriture est que le pilote implémente le blocage des fichiers de périphérique dans le pilote. Le processus de lecture et d'écriture peut être résumé comme suit : .

1. Définition - initialiser la tête de file d'attente
//定义等待队列头
wait_queue_head_t waitq_h;
//初始化,等待队列头
init_waitqueue_head(wait_queue_head_t *q);
 //或
//定义并初始化等待队列头
DECLARE_WAIT_QUEUE_HEAD(waitq_name);
Copier après la connexion

Parmi les options ci-dessus, la dernière définira et initialisera directement un en-tête d'attente. Cependant, si vous utilisez des variables globales pour transmettre des paramètres dans le module, celle à utiliser dépend de vos besoins.

Nous pouvons retracer le code source et voir ce que font les lignes ci-dessus :

//include/linux/wait.h 
 35 struct __wait_queue_head { 
 36         spinlock_t              lock;
 37         struct list_head        task_list;
 38 };
 39 typedef struct __wait_queue_head wait_queue_head_t;
Copier après la connexion

«

wait_queue_head_t –36–>Le spin lock utilisé par cette file d'attente
–27–>Le lien qui « enchaîne » toute la file d’attente

Jetons ensuite un œil à la macro d'initialisation :

 55 #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           \
 56         .lock           = __SPIN_LOCK_UNLOCKED(name.lock),              \
 57         .task_list      = { &(name).task_list, &(name).task_list } }
 58 
 59 #define DECLARE_WAIT_QUEUE_HEAD(name) \
 60         wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
Copier après la connexion

«

DECLARE_WAIT_QUEUE_HEAD() –60–>Créez une tête de file d'attente nommée name en fonction du nom de la chaîne entrante
–57–>Pour initialiser le champ task_list ci-dessus, la macro d'initialisation standard du noyau n'est pas utilisée. . .

2. Ajoutez ce processus à la file d'attente

Ajoutez des événements à la file d'attente, c'est-à-dire que le processus entre en état de veille et ne revient que lorsque la condition est vraie. La version de **_interruptible

indique que le sommeil peut être interrompu, et la version de _timeout** indique la version du délai d'attente, qui sera renvoyée lorsque le délai d'attente se produit. Cette convention de dénomination peut être vue partout dans l'API du noyau.

void wait_event(wait_queue_head_t *waitq_h,int condition);
void wait_event_interruptible(wait_queue_head_t *waitq_h,int condition);
void wait_event_timeout(wait_queue_head_t *waitq_h,int condition);
void wait_event_interruptible_timeout(wait_queue_head_t *waitq_h,int condition);
Copier après la connexion

C'est le cœur de la file d'attente, jetons un coup d'oeil

wait_event
└── wait_event
└──
_wait_event
├── abort_exclusive_wait
├── finish_wait
├── prepare_to_wait_event
└── ___wait_is_interruptible

244 #define wait_event(wq, condition)                                       \
245 do {                                                                    \
246         if (condition)                                                  \
247                 break;                                                  \
248         __wait_event(wq, condition);                                    \ 
249 } while (0)
Copier après la connexion

wait_event
–246–>如果condition为真,立即返回
–248–>否则调用__wait_event

194 #define ___wait_event(wq, condition, state, exclusive, ret, cmd)        \       
195 ({                                                                      \
206         for (;;) {                                                      \
207                 long __int = prepare_to_wait_event(&wq, &__wait, state);\
208                                                                         \  
209                 if (condition)                                          \       
210                         break;                                          \
212                 if (___wait_is_interruptible(state) && __int) {         \
213                         __ret = __int;                                  \
214                         if (exclusive) {                                \
215                                 abort_exclusive_wait(&wq, &__wait,      \
216                                                      state, NULL);      \
217                                 goto __out;                             \
218                         }                                               \
219                         break;                                          \
220                 }                                                       \
222                 cmd;                                                    \
223         }                                                               \
224         finish_wait(&wq, &__wait);                                      \
225 __out:  __ret;                                                          \
226 })
Copier après la connexion

___wait_event
–206–>死循环的轮询
–209–>如果条件为真,跳出循环,执行finish_wait();进程被唤醒
–212–>如果进程睡眠的方式是interruptible的,那么当中断来的时候也会abort_exclusive_wait被唤醒
–222–>如果上面两条都不满足,就会回调传入的schedule(),即继续睡眠

模板

struct wait_queue_head_t xj_waitq_h;
static ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
    if(!condition)    //条件可以在中断处理函数中置位
        wait_event_interruptible(&xj_waitq_h,condition);
}
static file_operations fops = {
    .read = demo_read,
};
static __init demo_init(void)
{
    init_waitqueue_head(&xj_waitq_h);
}
Copier après la connexion

IO多路复用的实现

对于普通的非阻塞IO,我们只需要在驱动中注册的read/write接口时不使用阻塞机制即可,这里我要讨论的是IO多路复用,即当驱动中的read/write并没有实现阻塞机制的时候,我们如何利用内核机制来在驱动中实现对IO多路复用的支持。下面这个就是我们要用的API

int poll(struct file *filep, poll_table *wait);
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)  
Copier après la connexion

当应用层调用select/poll/epoll机制的时候,内核其实会遍历回调相关文件的驱动中的poll接口,通过每一个驱动的poll接口的返回值,来判断该文件IO是否有相应的事件发生,我们知道,这三种IO多路复用的机制的核心区别在于内核中管理监视文件的方式,分别是数组链表,但对于每一个驱动,回调的接口都是poll。

模板

struct wait_queue_head_t waitq_h;
static unsigned int demo_poll(struct file *filp, struct poll_table_struct *pts)
{
    unsigned int mask = 0;
    poll_wait(filp, &wwaitq_h, pts);
    if(counter){
        mask = (POLLIN | POLLRDNORM);
    }
    return mask;
}

static struct file_operations fops = {
    .owner  = THIS_MODULE,
    .poll   = demo_poll,
};
static __init demo_init(void)
{
    init_waitqueue_head(&xj_waitq_h);
}
Copier après la connexion

其他API

刚才我们讨论了如何使用等待队列实现阻塞IO,非阻塞IO,其实关于等待队列,内核还提供了很多其他API用以完成相关的操作,这里我们来认识一下

//在等待队列上睡眠
sleep_on(wait_queue_head_t *wqueue_h);
sleep_on_interruptible(wait_queue_head_t *wqueue_h);

//唤醒等待的进程
void wake_up(wait_queue_t *wqueue);
void wake_up_interruptible(wait_queue_t *wqueue);
Copier après la connexion

总之,设备阻塞/非阻塞读写是Linux驱动程序编写过程中不可或缺的一部分。它可以实现高效的数据传输和事件处理,提高系统的性能和响应速度。希望本文能够帮助读者更好地理解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!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Vous avez un jeu croisé?
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

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

Différence entre Centos et Ubuntu Différence entre Centos et Ubuntu Apr 14, 2025 pm 09:09 PM

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)

Comment installer CentOS Comment installer CentOS Apr 14, 2025 pm 09:03 PM

É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.

Le choix de Centos après l'arrêt de l'entretien Le choix de Centos après l'arrêt de l'entretien Apr 14, 2025 pm 08:51 PM

CentOS a été interrompu, les alternatives comprennent: 1. Rocky Linux (meilleure compatibilité); 2. Almalinux (compatible avec CentOS); 3. Serveur Ubuntu (configuration requise); 4. Red Hat Enterprise Linux (version commerciale, licence payante); 5. Oracle Linux (compatible avec Centos et Rhel). Lors de la migration, les considérations sont: la compatibilité, la disponibilité, le soutien, le coût et le soutien communautaire.

Comment utiliser Docker Desktop Comment utiliser Docker Desktop Apr 15, 2025 am 11:45 AM

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).

Explication détaillée du principe docker Explication détaillée du principe docker Apr 14, 2025 pm 11:57 PM

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.

Que faire si l'image Docker échoue Que faire si l'image Docker échoue Apr 15, 2025 am 11:21 AM

Dépannage des étapes pour la construction d'image Docker échouée: cochez la syntaxe Dockerfile et la version de dépendance. Vérifiez si le contexte de construction contient le code source et les dépendances requis. Affichez le journal de construction pour les détails d'erreur. Utilisez l'option - cibler pour créer une phase hiérarchique pour identifier les points de défaillance. Assurez-vous d'utiliser la dernière version de Docker Engine. Créez l'image avec --t [Image-Name]: Debug Mode pour déboguer le problème. Vérifiez l'espace disque et assurez-vous qu'il est suffisant. Désactivez SELINUX pour éviter les interférences avec le processus de construction. Demandez de l'aide aux plateformes communautaires, fournissez Dockerfiles et créez des descriptions de journaux pour des suggestions plus spécifiques.

Que faire après Centos arrête la maintenance Que faire après Centos arrête la maintenance Apr 14, 2025 pm 08:48 PM

Une fois CentOS arrêté, les utilisateurs peuvent prendre les mesures suivantes pour y faire face: sélectionnez une distribution compatible: comme Almalinux, Rocky Linux et CentOS Stream. Migrez vers les distributions commerciales: telles que Red Hat Enterprise Linux, Oracle Linux. Passez à Centos 9 Stream: Rolling Distribution, fournissant les dernières technologies. Sélectionnez d'autres distributions Linux: comme Ubuntu, Debian. Évaluez d'autres options telles que les conteneurs, les machines virtuelles ou les plates-formes cloud.

Quelle configuration de l'ordinateur est requise pour VScode Quelle configuration de l'ordinateur est requise pour VScode Apr 15, 2025 pm 09:48 PM

Vs Code Système Exigences: Système d'exploitation: Windows 10 et supérieur, MacOS 10.12 et supérieur, processeur de distribution Linux: minimum 1,6 GHz, recommandé 2,0 GHz et au-dessus de la mémoire: minimum 512 Mo, recommandée 4 Go et plus d'espace de stockage: Minimum 250 Mo, recommandée 1 Go et plus d'autres exigences: connexion du réseau stable, xorg / wayland (Linux) recommandé et recommandée et plus

See all articles