Quel est le rôle des softirqs Linux et des files d'attente de travail

青灯夜游
Libérer: 2022-04-14 16:41:32
original
2575 Les gens l'ont consulté

La fonction des interruptions logicielles et des files d'attente de travail sous Linux est d'implémenter le traitement des interruptions. Les interruptions logicielles et les files d'attente de travail sont les mécanismes de mise en œuvre de la moitié inférieure des mécanismes d'interruption supérieurs et inférieurs. Les interruptions logicielles ne peuvent pas mettre en veille, bloquer ou basculer entre les processus et ne peuvent être interrompues que par des interruptions matérielles, tandis que la file d'attente de travail peut se mettre en veille ou être bloquée et peut basculer entre différents processus pour effectuer différentes tâches.

Quel est le rôle des softirqs Linux et des files d'attente de travail

L'environnement d'exploitation de ce tutoriel : système linux5.9.8, ordinateur Dell G3.

La fonction des interruptions logicielles et des files d'attente de travail sous Linux est d'implémenter le traitement des interruptions.

1. Concept d'interruption

L'interruption fait référence au CPU qui arrête temporairement le programme en cours d'exécution en raison d'événements internes et externes ou provoqués par des événements prédéfinis par le programme pendant le fonctionnement normal du CPU, et passe à la place au événements internes ou externes ou services d'événements pré-arrangés, puis revenez pour continuer à exécuter le programme temporairement interrompu une fois le service terminé. Linux est généralement divisé en interruptions externes (également appelées interruptions matérielles) et interruptions internes (également appelées exceptions).

En mode adresse réelle, le CPU utilise l'espace 1 Ko à partir de 0 dans la mémoire comme table de vecteurs d'interruption. Chaque entrée du tableau occupe 4 octets. Cependant, en mode protégé, la table des vecteurs d'interruption composée de ces entrées de 4 octets ne répond pas aux besoins réels. Par conséquent, sur la base des informations reflétant le changement de mode et le décalage, l'entrée de la table des vecteurs d'interruption est composée de 8 octets. La table des vecteurs d'interruption est également appelée table des descripteurs d'interruption (IDT). Un registre (IDTR) utilisé pour décrire la table des descripteurs d'interruption est ajouté à la CPU pour enregistrer l'adresse de départ de la table des descripteurs d'interruption.

2. Traitement des interruptions Linux

2.1 Numéro d'interruption système

D'après la définition d'interruption ci-dessus, on peut voir qu'un total de 256 entrées de vecteur d'interruption peuvent être enregistrées dans la table des vecteurs d'interruption système, ce qui sont les 256 descriptions d'interruption contenues dans le symbole IDT (correspondant à 256 vecteurs d'interruption).

 Les vecteurs d'interruption 0 à 31 sont réservés par Intel pour gérer les événements anormaux et ne peuvent pas être utilisés à d'autres fins. Pour les vecteurs d'interruption n° 0 à 31, le système d'exploitation n'a besoin que de fournir un gestionnaire d'exceptions. Lorsqu'une exception se produit, le processeur transférera automatiquement le contrôle à l'entrée du gestionnaire correspondant et exécutera en fait le gestionnaire correspondant ; 32 vecteurs d'interruption qui gèrent les exceptions, la version 2.6 de Linux ne fournit que des gestionnaires pour les vecteurs d'interruption n° 0 à 17. Pour les gestionnaires correspondants, veuillez vous référer au tableau suivant, vecteur d'interruption et tableau de correspondance des événements d'exception ; , Les vecteurs d'interruption n° 17 à 31 sont vides et inutilisés.

Numéro de vecteur d'interruption

pide_error1Débogage Exception Octet unique, int 3Int367891011 _protection14Exception de pagePage_fault 15 (Intel réservé)Spurious_interrupt_bug16Erreur du coprocesseurErreur_coprocesseur17 Alignement contrôle interrompuAlignment_check

  Les vecteurs d'interruption 0 à 31 ont été réservés, donc un total de 224 vecteurs d'interruption 32 à 255 sont disponibles. Comment ces 224 vecteurs d’interruption sont-ils alloués ? Dans la version 2.6 de Linux, à l'exception de 0x80 (SYSCALL_VECTOR) qui est utilisé comme appel systèmeentrée générale, les autres sont utilisés pour les sources d'interruption matérielles externes, y compris les 15 irqs du contrôleur d'interruption programmable 8259A ; Lorsque CONFIG_X86_IO_APIC n'est pas défini, seuls 15 des 223 autres vecteurs d'interruption (sauf 0x80) à partir du 32 sont utilisés, et les 208 autres restent vides.

 2.2 Demande d'interruption

 2.2.1 Présentation de la demande d'interruption

Interruption correspondante.

 L'appareil envoie un niveau élevé au contrôleur d'interruption via la ligne d'interruption correspondante pour générer un signal d'interruption, et le système d'exploitation obtiendra l'interruption générée sur cette ligne d'interruption à partir du bit d'état du contrôleur d'interruption. Et ce n'est que lorsque l'appareil contrôle une certaine ligne d'interruption qu'il peut envoyer un signal à cette ligne d'interruption. De plus, comme il existe aujourd'hui de plus en plus de périphériques, les lignes d'interruption sont des ressources très précieuses et ne peuvent pas être mappées une à une. Par conséquent, avant d'utiliser la ligne d'interruption, vous devez demander la ligne d'interruption correspondante. Que la méthode d'interruption partagée ou une interruption exclusive soit utilisée, le processus d'application consiste d'abord à analyser toutes les lignes d'interruption pour découvrir celles qui ne sont pas occupées par d'autres, et à en sélectionner une comme IRQ du périphérique. Deuxièmement, demandez l'IRQ correspondante via la fonction d'application d'interruption. Enfin, vérifiez si l'interruption peut être exécutée en fonction du résultat de l'application.

  2.2.2 Structures liées aux interruptions

  La structure de base des données de traitement dans les interruptions est irq_desc, qui décrit complètement une ligne d'interruption, Linux 2.6. Le code source de 22.6 est le suivant. DIRQ_DESC
Définition dans include/Linux/IRQ.H

R
/**
 * struct irq_desc - interrupt descriptor
 *
 * @handle_irq:        highlevel irq-events handler [if NULL, __do_IRQ()]
 * @chip:        low level interrupt hardware access
 * @msi_desc:        MSI descriptor
 * @handler_data:    per-IRQ data for the irq_chip methods
 * @chip_data:        platform-specific per-chip private data for the chip
 *            methods, to allow shared chip implementations
 * @action:        the irq action chain
 * @status:        status information
 * @depth:        disable-depth, for nested irq_disable() calls
 * @wake_depth:        enable depth, for multiple set_irq_wake() callers
 * @irq_count:        stats field to detect stalled irqs
 * @irqs_unhandled:    stats field for spurious unhandled interrupts
 * @lock:        locking for SMP
 * @affinity:        IRQ affinity on SMP
 * @cpu:        cpu index useful for balancing
 * @pending_mask:    pending rebalanced interrupts
 * @dir:        /proc/irq/ procfs entry
 * @affinity_entry:    /proc/irq/smp_affinity procfs entry on SMP
 * @name:        flow handler name for /proc/interrupts output */struct irq_desc {
    irq_flow_handler_t    handle_irq;    struct irq_chip        *chip;    struct msi_desc        *msi_desc;    void            *handler_data;    void            *chip_data;    struct irqaction    *action;    /* IRQ action list */
    unsigned int        status;        /* IRQ status */

    unsigned int        depth;        /* nested irq disables */
    unsigned int        wake_depth;    /* nested wake enables */
    unsigned int        irq_count;    /* For detecting broken IRQs */
    unsigned int        irqs_unhandled;
    spinlock_t        lock;
#ifdef CONFIG_SMP
    cpumask_t        affinity;
    unsigned int        cpu;#endif#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
    cpumask_t        pending_mask;#endif#ifdef CONFIG_PROC_FS    struct proc_dir_entry    *dir;#endif
    const char        *name;
} ____cacheline_internodealigned_in_smp;
Copier après la connexion
E

IRQ_DESC Elle est la suivante :

définie dans include/linux/interrupt.h Structure d'action d'interruption : struct irqaction

struct irqaction {
    irq_handler_t handler;
    unsigned long flags;
    cpumask_t mask;    const char *name;    void *dev_id;    struct irqaction *next;    int irq;    struct proc_dir_entry *dir;
};
Copier après la connexion

Défini dans include/linux : collection de fonctions de traitement liées à la puce irq_chip

/**
 * struct irq_chip - hardware interrupt chip descriptor
 *
 * @name:        name for /proc/interrupts
 * @startup:        start up the interrupt (defaults to ->enable if NULL)
 * @shutdown:        shut down the interrupt (defaults to ->disable if NULL)
 * @enable:        enable the interrupt (defaults to chip->unmask if NULL)
 * @disable:        disable the interrupt (defaults to chip->mask if NULL)
 * @ack:        start of a new interrupt
 * @mask:        mask an interrupt source
 * @mask_ack:        ack and mask an interrupt source
 * @unmask:        unmask an interrupt source
 * @eoi:        end of interrupt - chip level
 * @end:        end of interrupt - flow level
 * @set_affinity:    set the CPU affinity on SMP machines
 * @retrigger:        resend an IRQ to the CPU
 * @set_type:        set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
 * @set_wake:        enable/disable power-management wake-on of an IRQ
 *
 * @release:        release function solely used by UML
 * @typename:        obsoleted by name, kept as migration helper */struct irq_chip {    const char    *name;
    unsigned int    (*startup)(unsigned int irq);  //中断开始    void        (*shutdown)(unsigned int irq);    //中断关闭    void        (*enable)(unsigned int irq);      //中断使能    void        (*disable)(unsigned int irq);    //中断禁用    void        (*ack)(unsigned int irq);    void        (*mask)(unsigned int irq);    void        (*mask_ack)(unsigned int irq);    void        (*unmask)(unsigned int irq);    void        (*eoi)(unsigned int irq);    void        (*end)(unsigned int irq);    void        (*set_affinity)(unsigned int irq, cpumask_t dest);    int        (*retrigger)(unsigned int irq);    int        (*set_type)(unsigned int irq, unsigned int flow_type);    int        (*set_wake)(unsigned int irq, unsigned int on);    /* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHOD    void        (*release)(unsigned int irq, void *dev_id);#endif
    /*
     * For compatibility, ->typename is copied into ->name.
     * Will disappear.     */
    const char    *typename;
};
Copier après la connexion

2.2.3 Implémentation de la demande d'interruption

mécanisme des moitiés supérieure et inférieure

Nous espérons que le gestionnaire d'interruption fonctionnera rapidement, et Je veux qu'il accomplisse plus de travail. Ces deux objectifs se limitent mutuellement, comment résoudre le ——mécanisme de la moitié supérieure et inférieure

.

Nous avons réduit de moitié la gestion des interruptions. Le gestionnaire d'interruption est la partie supérieure - accepte l'interruption et il commence à s'exécuter immédiatement, mais il ne peut fonctionner qu'avec une limite de temps stricte. Les travaux qui pourront être achevés ultérieurement seront reportés au second semestre, puis, le moment venu, le second semestre sera ouvert à l'exécution. La première moitié est simple et rapide, et désactive tout ou partie des interruptions pendant l'exécution

.

 La seconde moitié sera exécutée plus tard, et toutes les interruptions pourront recevoir une réponse pendant l'exécution. Cette conception peut rendre le système en état de protection contre les interruptions aussi court que possible, améliorant ainsi la réactivité du système. La moitié supérieure n'a que le mécanisme de gestion des interruptions, tandis que la moitié inférieure a une implémentation d'interruption logicielle, une implémentation de tasklet

et une implémentation de file d'attente de travail.

Nous utilisons des cartes réseau pour expliquer ces deux moitiés. Lorsque la carte réseau reçoit le paquet de données, elle en informe le noyau et déclenche une interruption. La première moitié consiste à lire le paquet de données dans la mémoire à temps pour éviter toute perte due à un retard. Après avoir lu la mémoire, le traitement de ces données n'est plus urgent. A ce moment, le noyau peut exécuter le programme qui a été exécuté avant l'interruption, et le traitement des paquets de données réseau est laissé à la moitié inférieure.

Principe de division des moitiés supérieure et inférieure

  1)

Si une tâche est très sensible au temps, placez-la dans le gestionnaire d'interruption pour exécution 

 ;

 2) Si une tâche est liée au matériel, placez-la dans le gestionnaire d'interruption pour exécution

 3) Si une tâche veut s'assurer qu'elle n'est pas interrompue par d'autres interruptions, mettez-la dans l'interruption ; handler Execution ;

  4) Pour toutes les autres tâches, pensez à les placer dans la moitié inférieure pour l'exécution.

Interruption douce du mécanisme de mise en œuvre de la moitié inférieure

En tant que représentant du mécanisme de la moitié inférieure, l'interruption douce est née avec l'émergence de SMP (processeur de mémoire partagée), et c'est aussi La base de l'implémentation de tasklet (taskletajoute en fait simplement un certain mécanisme basé sur des interruptions logicielles). Softirq est généralement le terme général pour "fonction reportable", incluant parfois tasklet (les lecteurs sont invités à déduire si tasklet est inclus en fonction du contexte lorsqu'ils le rencontrent). Cela semble parce qu'il doit satisfaire à la distinction entre les moitiés supérieure et inférieure proposée ci-dessus, afin que les tâches insensibles au temps puissent être différées. L'interruption logicielle exécute les tâches restantes qui lui sont laissées par le gestionnaire d'interruption et peut être exécutée en parallèle sur plusieurs . Le CPU augmente l'efficacité globale du système. Ses fonctionnalités incluent :

a) Il ne peut pas être exécuté immédiatement après sa génération, et il doit attendre la planification du noyau avant de l'exécuter. peut être exécuté. Les interruptions logicielles ne peuvent pas être interrompues d'elles-mêmes, mais ne peuvent être interrompues que par des interruptions matérielles (partie supérieure).

 b) peut s'exécuter simultanément sur plusieurs CPU (même du même type). Par conséquent, les interruptions logicielles doivent être conçues comme des fonctions réentrantes (permettant à plusieurs CPU de fonctionner en même temps), de sorte que des verrous tournants doivent également être utilisés pour protéger leurs structures de données.

La moitié inférieure du mécanisme d'implémentation tasklet

Tasklet est implémentée via des interruptions logicielles, elle est donc elle-même également une interruption logicielle.

  Les interruptions logicielles sont traitées de manière par interrogation. S'il s'agit du dernier type d'interruption, tous les types d'interruption doivent être parcourus avant que la fonction de traitement correspondante puisse finalement être exécutée. Évidemment, afin de garantir l'efficacité du sondage, les développeurs ont limité le nombre d'interruptions à 32.

 Afin d'augmenter le nombre de traitements d'interruption et d'améliorer l'efficacité du traitement, le mécanisme tasklet a été créé.

  Tasklet adopte un mécanisme de file d'attente indifférenciée et n'est exécuté qu'en cas d'interruption, éliminant ainsi la difficulté de la recherche cyclique de table. TaskletEn tant que nouveau mécanisme, il peut évidemment présenter plus d'avantages. À cette époque, SMP devenait de plus en plus populaire, c'est pourquoi le mécanisme SMP a été ajouté à tasklet pour garantir que le même type d'interruption ne peut être exécuté que sur un seul cpu. À l’ère des interruptions douces, une telle considération n’existait évidemment pas. Par conséquent, la même interruption logicielle peut être exécutée sur deux cpu en même temps, ce qui est susceptible de provoquer des conflits.

Résumé des avantages de tasklet :

  (1 ) Aucune limite sur le nombre de types

  (2 ) Haute efficacité, pas besoin de rechercher une table en boucle

Prise en charge du mécanisme SMP ; les fonctionnalités sont les suivantes : ) un Ce type de

tasklet

spécifique ne peut fonctionner que sur un seul CPU et ne peut pas être exécuté en parallèle, mais ne peut être exécuté qu'en série.

 2) Plusieurs tasklets de types différents peuvent être exécutées en parallèle sur plusieurs CPU.

 3) Les interruptions logicielles sont allouées de manière statique et ne peuvent pas être modifiées une fois le noyau compilé. Mais tasklet est beaucoup plus flexible et peut être modifié au moment de l'exécution (par exemple lors de l'ajout de modules).

La moitié inférieure du mécanisme d'implémentation - file d'attente de travail

La fonction différée que nous avons introduite ci-dessus s'exécute dans le contexte d'interruption (un point de contrôle de l'interruption logicielle est

do_IRQheure de sortie), qui a causé quelques problèmes : les interruptions logicielles ne peuvent pas dormir ou se bloquer. Étant donné que le contexte d'interruption est dans l'état du noyau et qu'il n'y a pas de commutation de processus, si l'interruption logicielle est mise en veille ou bloquée, elle ne pourra pas quitter cet état, provoquant le gel de l'ensemble du noyau. Cependant, les fonctions de blocage ne peuvent pas être implémentées dans le contexte d'interruption et doivent être exécutées dans le contexte de processus, comme les fonctions qui accèdent aux blocs de données du disque. Par conséquent, les fonctions de blocage ne peuvent pas être implémentées à l'aide de softirqs. Mais ils ont souvent des propriétés reportables.

Les fonctions différées que nous avons introduites ci-dessus s'exécutent dans le contexte d'interruption, ce qui entraîne certains problèmes, indiquant qu'elles ne peuvent pas être suspendues, ce qui signifie que les interruptions logicielles ne peuvent pas dormir ou se bloquer. La raison en est que le contexte d'interruption est en dehors. l'état du noyau, il n'y a pas de commutation de processus, donc si l'interruption logicielle se met en veille ou est bloquée, elle ne pourra pas quitter cet état, provoquant le gel de l'ensemble du noyau. Par conséquent, les fonctions de blocage ne peuvent pas être implémentées à l'aide de softirqs. Mais ils ont souvent des propriétés reportables. Et comme il est exécuté en série, tant qu'un temps de traitement est long, cela entraînera un retard dans la réponse des autres interruptions. Afin d'accomplir ces tâches impossibles, une file d'attente de travail a émergé, qui peut basculer entre différents processus pour accomplir différentes tâches.

  Si la tâche reportée nécessite du sommeil, choisissez la file d'attente de travail. Si le sommeil n'est pas requis, choisissez une interruption douce ou tasklet. Les files d'attente de travail peuvent s'exécuter dans un contexte de processus et déléguer le travail à un thread du noyau. Pour faire simple, la file d'attente de travail est un groupe de threads du noyau, utilisés comme threads du démon d'interruption. Plusieurs interruptions peuvent être placées dans un thread, ou chaque interruption peut se voir attribuer un thread. Nous utilisons la structure workqueue_struct pour représenter le thread de travail, qui est implémenté à l'aide du thread du noyau. Comment le thread de travail exécute-t-il le travail reporté——Il existe une telle liste chaînée, qui se compose de la structure work_struct, et ce work_struct décrit un travail une fois le travail terminé, le work_struct correspondant. L'objet est supprimé de la liste chaînée. Lorsqu'il n'y a plus d'objets dans la liste chaînée, le thread de travail continue de dormir. Étant donné que les files d'attente de travail sont des threads, nous pouvons utiliser toutes les méthodes pouvant être utilisées dans les threads.

Quel est le rôle des interruptions logicielles et des files d'attente de travail sous Linux Le rôle des interruptions logicielles et des files d'attente de travail sous Linux est d'implémenter le traitement des interruptions ; demi-mécanisme de mise en œuvre dans les mécanismes supérieur et inférieur.

  1.L'interruption logicielle est généralement le nom général de "fonction différée

"

Elle ne peut pas dormir ou se bloquer. Elle est dans le contexte d'interruption et ne peut pas basculer entre les processus. L'interruption logicielle ne peut pas être interrompue par elle-même. . Peut être interrompu par des interruptions matérielles (partie supérieure) et peut s'exécuter simultanément sur plusieurs CPU. Par conséquent, les interruptions logicielles doivent être conçues comme des fonctions réentrantes, des verrous tournants sont donc également nécessaires pour protéger leurs structures de données.   2.La fonction dans la file d'attente de travail est dans le contexte du processus. Elle peut dormir ou être bloquée et peut basculer entre différents processus pour effectuer différentes tâches.

Ni la fonction différée ni la file d'attente de travail ne peuvent accéder à l'espace de processus de l'utilisateur. Il ne peut y avoir de processus en cours d'exécution lorsque la fonction différée est exécutée par le processus du noyau et elle ne peut pas accéder à l'espace de processus. adresse de l'espace utilisateur. Recommandations associées : "

Tutoriel vidéo Linux

"

4
Opcode invalide Invalid_op
Device_not_available Device_not_available
Double_fault Double_fault
Dépassement du segment du coprocesseur Coprocessor_segment_overrun
TSS invalide Incalid_tss
Interruption de segment manquant Segment_not_present générale

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!

Étiquettes associées:
source:php.cn
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!