GNU/Linux >> Tutoriels Linux >  >> Linux

Comment une interruption est-elle gérée sous Linux ?

Voici une vue de haut niveau du traitement de bas niveau. Je décris une architecture typique simple, les architectures réelles peuvent être plus complexes ou différer d'une manière qui n'a pas d'importance à ce niveau de détail.

Lorsqu'une interruption se produit, le processeur regarde si les interruptions sont masquées. S'ils le sont, rien ne se passe jusqu'à ce qu'ils soient démasqués. Lorsque les interruptions sont démasquées, s'il y a des interruptions en attente, le processeur en choisit une.

Ensuite, le processeur exécute l'interruption en se branchant à une adresse particulière en mémoire. Le code à cette adresse s'appelle le gestionnaire d'interruption. Lorsque le processeur s'y connecte, il masque les interruptions (de sorte que le gestionnaire d'interruptions a le contrôle exclusif) et enregistre le contenu de certains registres à un endroit (généralement d'autres registres).

Le gestionnaire d'interruption fait ce qu'il doit faire, généralement en communiquant avec le périphérique qui a déclenché l'interruption pour envoyer ou recevoir des données. Si l'interruption a été déclenchée par le minuteur, le gestionnaire peut déclencher le planificateur du système d'exploitation pour passer à un autre thread. Lorsque le gestionnaire a fini de s'exécuter, il exécute une instruction spéciale de retour à partir d'une interruption qui restaure les registres sauvegardés et démasque les interruptions.

Le gestionnaire d'interruption doit s'exécuter rapidement, car il empêche toute autre interruption de s'exécuter. Dans le noyau Linux, le traitement des interruptions est divisé en deux parties :

  • La "moitié supérieure" est le gestionnaire d'interruption. Il fait le minimum nécessaire, communique généralement avec le matériel et définit un indicateur quelque part dans la mémoire du noyau.
  • La "moitié inférieure" effectue tout autre traitement nécessaire, par exemple la copie de données dans la mémoire de processus, la mise à jour des structures de données du noyau, etc. Elle peut prendre son temps et même bloquer l'attente d'une autre partie du système car elle s'exécute avec des interruptions activé.

Comme d'habitude sur ce sujet, pour plus d'informations, lisez Pilotes de périphériques Linux; le chapitre 10 concerne les interruptions.


Gilles a déjà décrit le cas général d'une interruption, ce qui suit s'applique spécifiquement à Linux 2.6 sur une architecture Intel (une partie de ceci est également basée sur les spécifications d'Intel).

Une interruption est un événement qui modifie la séquence d'instructions exécutées par le processeur.
Il existe deux types d'interruptions :

  • Interruption synchrone (Exception) produit par le CPU lors du traitement des instructions
  • Interruption asynchrone (interruption) émis par d'autres périphériques matériels

Les exceptions sont causées par des erreurs de programmation (par exemple, erreur de division , Défaut de page , Débordement ) qui doit être géré par le noyau. Il envoie un signal au programme et essaie de récupérer de l'erreur.

Les deux exceptions suivantes sont classées :

  • Exception détectée par le processeur généré par le CPU lors de la détection d'une condition anormale ; répartis en trois groupes :Défauts peuvent généralement être corrigés, Pièges signaler une exécution, Annuler sont des erreurs graves.
  • Exception programmée demandé par le programmeur, géré comme un piège.

Les interruptions peuvent être émises par des périphériques d'E/S (clavier, carte réseau, ..), des temporisateurs d'intervalle et (sur les systèmes multiprocesseurs) d'autres processeurs. Lorsqu'une interruption se produit, le CPU doit arrêter son instruction en cours et exécuter l'interruption nouvellement arrivée. Il doit sauvegarder l'ancien état de processus interrompu pour (probablement) le reprendre une fois l'interruption traitée.

La gestion des interruptions est une tâche sensible :

  • Des interruptions peuvent survenir à tout moment, le noyau essaie de s'en débarrasser dès que possible
  • Une interruption peut être interrompue par une autre interruption
  • Certaines régions du noyau ne doivent en aucun cas être interrompues

Deux niveaux d'interruption différents sont définis :

  • Interruptions masquables émis par les périphériques d'E/S ; peut être dans deux états, masqué ou non masqué. Seules les interruptions non masquées sont traitées.
  • Interruptions non masquables; dysfonctionnements critiques (par exemple panne matérielle) ; toujours traité par le CPU.

Chaque périphérique matériel a sa propre ligne de demande d'interruption (IRQ). Les IRQ sont numérotées à partir de 0. Toutes les lignes IRQ sont connectées à un contrôleur d'interruption programmable (PIC). Le PIC écoute les IRQ et les affecte au CPU. Il est également possible de désactiver une ligne IRQ spécifique.
Les systèmes Linux multiprocesseurs modernes incluent généralement le nouveau Advanced PIC (APIC), qui distribue les requêtes IRQ de manière égale entre les processeurs.

L'étape intermédiaire entre une interruption ou une exception et sa gestion est la table des descripteurs d'interruption (IDT). Ce tableau associe chaque vecteur d'interruption ou d'exception (un nombre) à un gestionnaire spécifié (par exemple Divide error est géré par la fonction divide_error() ).

Grâce à l'IDT, le noyau sait exactement comment gérer l'interruption ou l'exception survenue.

Alors, que fait le noyau lorsqu'une interruption se produit ?

  • Le CPU vérifie après chaque instruction s'il y a une IRQ du (A)PIC
  • Si oui, consulte l'IDT pour mapper le vecteur reçu à une fonction
  • Vérifie si l'interruption a été émise par une source autorisée
  • Sauvegarde les registres du processus interrompu
  • Appelez la fonction correspondante pour gérer l'interruption
  • Chargez les registres récemment enregistrés du processus interrompu et essayez de le reprendre

Tout d'abord, les participants impliqués dans la gestion des interruptions sont les périphériques matériels, le contrôleur d'interruption, le processeur, le noyau du système d'exploitation et les pilotes. Les périphériques matériels sont responsables de la génération d'interruptions. Ils affirment les lignes de demande d'interruption lorsqu'ils veulent l'attention du noyau du système d'exploitation. Ces signaux sont multiplexés par le contrôleur d'interruption, qui est responsable de la collecte des signaux d'interruption. Il est également responsable de la détermination de l'ordre dans lequel les signaux d'interruption seront transmis au CPU. Le contrôleur d'interruption est capable de désactiver temporairement une ligne de demande d'interruption particulière (IRQL) et de la réactiver (masquage IRQL). Le contrôleur d'interruption transmet les demandes d'interruption collectées au CPU de manière séquentielle. La CPU après l'achèvement de l'exécution de chaque instruction, la CPU vérifie s'il y a des demandes d'interruption en attente du contrôleur d'interruption. Si la CPU trouve qu'il y a une demande en attente ET que l'indicateur d'activation d'interruption est défini dans le registre de contrôle interne de la CPU, la CPU commence la gestion des interruptions. Comme vous pouvez le voir, en manipulant l'indicateur d'interruption dans le CPU et en communiquant avec le contrôleur d'interruption, le noyau Linux est capable de contrôler l'acceptation des interruptions. Par exemple, Linux peut désactiver l'acceptation des interruptions d'un périphérique particulier ou désactiver complètement l'acceptation des interruptions.

Que se passe-t-il lorsque le processeur reçoit une demande d'interruption ? Tout d'abord, le processeur désactive automatiquement les interruptions en réinitialisant l'indicateur d'interruption. Ils seront réactivés une fois la gestion des interruptions terminée. Dans le même temps, le processeur effectue une quantité minimale de travail nécessaire pour faire passer le processeur du mode utilisateur au mode noyau de manière à lui permettre de reprendre l'exécution du code interrompu. Le CPU consulte les structures de contrôle spéciales du CPU remplies par le noyau Linux pour trouver une adresse de code à laquelle le contrôle sera passé. Cette adresse est l'adresse de la première instruction du gestionnaire d'interruptions, qui fait partie du noyau Linux.

Dans un premier temps, le noyau de gestion des interruptions identifie le vecteur d'interruption reçu pour identifier le type d'événement qui s'est produit dans le système. Le vecteur d'interruption définit les actions que Linux entreprendra pour le gérer. Dans un deuxième temps, Linux enregistre le reste des registres du CPU (qui n'a pas été enregistré automatiquement par le CPU) et qui peuvent potentiellement être utilisés par le programme interrompu. C'est une action très importante, car elle permet à Linux de gérer les interruptions de manière transparente en ce qui concerne le programme interrompu. Dans une troisième étape, Linux accomplit le passage en mode noyau en définissant l'environnement du noyau et en définissant l'état du processeur requis pour cela. Et enfin, vector le gestionnaire d'interruption dépendant est appelé. (Vous pouvez consulter la macro BUILD_INTERRUPT3 dans arch\x86\kernel\entry_32.S pour saisir les détails supplémentaires de l'exemple lié à l'architecture x86) Dans le cas des périphériques, il s'agit d'une routine do_IRQ(). (Regardez dans l'arch\x86\kernel\irq.c)

Le gestionnaire d'interruption dépendant du vecteur est généralement enveloppé par des appels à irq_enter() et irq_exit(). La zone de code incluse dans une paire de ces fonctions est atomique par rapport à toutes les autres zones de ce type et est également atomique par rapport aux paires de cli/sti. Irq_enter() et irq_exit() capturent également certaines statistiques liées à la gestion des interruptions. Enfin, le noyau examine la table vector_irq pour trouver le numéro irq attribué au vecteur de l'interruption reçue et appelle handle_irq() (depuis arch\x86\kernel \irq_32.c).

À ce stade, la partie commune de la gestion des interruptions sous Linux se termine, car le noyau regarde la routine de gestion des interruptions dépendante du périphérique installée par le pilote de périphérique comme faisant partie du descripteur irq et l'invoque. Si un tel gestionnaire n'a pas été installé par le pilote, le noyau reconnaît simplement l'interruption sur le contrôleur d'interruption et quitte le gestionnaire d'interruption général.

Après la fin de la gestion des interruptions, le noyau restaure l'état du programme qui a été interrompu précédemment et reprend l'exécution de ce programme.


Linux
  1. Comment installer Python sur Linux

  2. Comment j'utilise cron sous Linux

  3. Comment utiliser la commande Su sous Linux

  4. Introduction aux interruptions Linux et à l'affinité CPU SMP

  5. Comment \n et \r sont-ils gérés différemment sous Linux et Windows ?

Comment installer Kali Linux

Comment installer FFmpeg sur Linux

Comment tuer un processus sous Linux

Comment créer un fichier sous Linux

Comment renommer des répertoires sous Linux

Comment installer FreeOffice sur Linux