53 votes

Pourquoi le code du noyau/thread qui s'exécute dans un contexte d'interruption ne peut pas dormir ?

Je lis l'article suivant de Robert Love

http://www.linuxjournal.com/article/6916

qui dit

"...Discutons du fait que les files d'attente de travail fonctionnent dans un contexte de processus. Cela contraste avec les autres mécanismes de la moitié inférieure, qui fonctionnent tous dans un contexte d'interruption. Le code qui s'exécute dans un contexte d'interruption est incapable de dormir ou de se bloquer, parce que le contexte d'interruption n'a pas de processus de soutien avec lequel replanifier. Par conséquent, comme les gestionnaires d'interruption ne sont pas associés à un processus, il n'y a rien que le planificateur puisse mettre en sommeil et, plus important encore, rien qu'il puisse réveiller..."

Je ne comprends pas. AFAIK, l'ordonnanceur du noyau est O(1), il est implémenté par le bitmap. Alors qu'est-ce qui empêche le planificateur de mettre le contexte d'interruption en veille et de prendre le prochain processus planifiable et de lui passer le contrôle ?

6 votes

Notez que le patchset linux-rt rend les gestionnaires d'interruptions threadés, ce qui leur permet de dormir. Cela améliore la latence, mais les performances en prennent un coup.

1 votes

Cette question mérite un grand nombre de réviseurs, IMO, chaque programmeur de bas niveau a réfléchi à cette question au cours de sa carrière. voir aussi cet échange de mail hi.baidu.com/rwen2012/item/2040e7cace3c6a0dac092f3c

45voto

Keith Smith Points 1724

Alors qu'est-ce qui empêche le scehduler de mettre le contexte d'interruption en veille et de prendre le prochain processus planifiable et de lui passer le contrôle ?

Le problème est que le contexte d'interruption n'est pas un processus, et ne peut donc pas être mis en veille.

Lorsqu'une interruption se produit, le processeur enregistre les registres sur la pile et saute au début de la routine de service d'interruption. Cela signifie que lorsque le gestionnaire d'interruption s'exécute, il s'exécute dans le contexte du processus qui s'exécutait lorsque l'interruption s'est produite. L'interruption est exécutée sur la pile de ce processus, et lorsque le gestionnaire d'interruption est terminé, ce processus reprend son exécution.

Si vous essayez de dormir ou de bloquer à l'intérieur d'un gestionnaire d'interruptions, vous finirez par arrêter non seulement le gestionnaire d'interruptions, mais aussi le processus qu'il a interrompu. Cela peut être dangereux, car le gestionnaire d'interruption n'a aucun moyen de savoir ce que faisait le processus interrompu, ni même s'il est sûr que ce processus soit suspendu.

Un scénario simple où les choses pourraient mal tourner serait un blocage entre le gestionnaire d'interruptions et le processus qu'il interrompt.

  1. Processus1 entre en mode noyau.
  2. Processus1 acquiert LockA .
  3. L'interruption se produit.
  4. L'ISR commence à s'exécuter en utilisant Processus1 de la pile.
  5. L'ISR tente d'acquérir LockA .
  6. ISR appelle sleep pour attendre LockA pour être libéré.

A ce stade, vous êtes dans une impasse. Processus1 ne peut pas reprendre son exécution tant que l'ISR n'a pas terminé sa pile. Mais l'ISR est bloqué en attendant Processus1 pour libérer LockA .

0 votes

De plus, les interruptions nécessitent généralement un traitement très rapide, sinon vous risquez d'avoir toutes sortes de problèmes.

1 votes

OK..il y a deux arguments dans votre affirmation : 1. "Si vous avez essayé de mettre en veille ou de bloquer .... ou même s'il est sûr pour ce processus d'être suspendu." Je ne crois absolument pas à cet argument. Tout d'abord, le noyau ne se soucie pas de ce que fait le processus de l'espace utilisateur ou s'il est sûr de le suspendre. De plus, avec un noyau préemptif, il est même possible de bloquer un thread du noyau et d'en démarrer un autre. 2. "Dans le pire des cas, le blocage à partir d'un gestionnaire d'interruption pourrait causer des blocages" C'est un problème de verrouillage. Que se passe-t-il si mon ISR libère tous les verrous avant d'appeler sleep ?

0 votes

@Methos - Re 1. Le problème se pose lorsque vous interrompez un processus en mode noyau, et non un processus en mode utilisateur. Si vous interrompez un thread du noyau et laissez le gestionnaire bloquer, ce ne serait pas la même chose qu'une préemption normale de thread, car vous préempteriez simultanément deux contextes non liés, le thread du noyau et l'ISR. S'il y a des dépendances entre eux, vous êtes mort. D'où mon exemple sur le thread du noyau qui détient une ressource dont l'ISR a besoin. Le thread du noyau ne pourra pas continuer à s'exécuter tant que l'ISR ne sera pas terminé. Mais l'ISR attend le thread du noyau. Impasse.

36voto

arsane Points 6500

Je pense que c'est une idée de design.

Bien sûr, vous pouvez concevoir un système dans lequel vous pouvez dormir en étant interrompu, mais à part rendre le système difficile à comprendre et compliqué (beaucoup de situations à prendre en compte), cela ne sert à rien. Donc, du point de vue de la conception, déclarer le gestionnaire d'interruption comme ne pouvant pas dormir est très clair et facile à mettre en œuvre.


De Robert Love (un pirate du noyau) : http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791

Vous ne pouvez pas dormir dans un gestionnaire d'interruption parce que les interruptions n'ont pas un contexte de processus de soutien, et donc il n'y a rien à replanifier. dans ce contexte. En d'autres termes, les gestionnaires d'interruptions ne sont pas associés à une tâche, donc il n'y a rien à "mettre en sommeil" et (plus important) "rien à réveiller". Ils doivent s'exécuter de manière atomique.

Cela n'est pas différent des autres systèmes d'exploitation. Dans la plupart des systèmes d'exploitation, les interruptions ne sont pas threadées. Cependant, les moitiés inférieures le sont souvent.

La raison pour laquelle le gestionnaire de faute de page peut dormir est qu'il est invoqué seulement par le code qui s'exécute dans le contexte du processus. Parce que la mémoire propre du noyau du noyau n'est pas pagable, seuls les accès à la mémoire de l'espace utilisateur peuvent entraîner un défaut de page. défaut de page. Ainsi, seuls certains endroits (comme les appels à copy_{to,from}_user()) peuvent provoquer un défaut de page dans le noyau. Ces Ces endroits doivent tous être faits par du code qui peut dormir (c'est-à-dire, le contexte du processus, pas de verrous, et cetera).

0 votes

Je suis arrivé à la même conclusion. Mais je ne suis pas sûr de pouvoir étayer cette affirmation. Je voulais juste savoir s'il y avait une raison "mathématique" de ne pas le faire.

0 votes

Je ne sais pas comment vous pourriez prouver, au sens "mathématique", qu'il est impossible de construire un système qui permette à un ISR de dormir. Mais j'ai programmé à l'intérieur d'un certain nombre de systèmes d'exploitation, et aucun d'entre eux ne le permet. En pratique, ce que j'ai vu de plus proche pour permettre à un gestionnaire d'interruptions de faire des choses comme dormir est d'avoir un processus explicite qui fait le travail de gestion des interruptions. Mais les systèmes que j'ai vus qui font cela (par exemple, Solaris) ont toujours un ISR minimal qui n'est pas autorisé à faire des choses comme dormir. Tout ce qu'il fait est de réveiller le fil d'interruption et de le laisser faire le vrai travail.

0 votes

@Keith, ce problème ne semble pas avoir de réponse de l'autorité, bien que je pense qu'il est possible de concevoir un système que l'ISR peut dormir. J'ai joint ici la réponse de Robert Love à cette question, mais de mon point de vue, je pense que c'est une idée de conception.

7voto

Tony Lee Points 3388

Parce que l'infrastructure de commutation des fils est inutilisable à ce moment-là. Lors de la prise en charge d'une interruption, seuls les trucs de plus haute priorité peuvent s'exécuter - Voir le Manuel du développeur de logiciels Intel sur la priorité des interruptions, des tâches et du processeur. . Si vous autorisiez l'exécution d'un autre thread (ce que vous laissez entendre dans votre question que ce serait facile à faire), vous ne pourriez pas le laisser faire quoi que ce soit - s'il causait un défaut de page, vous devriez utiliser les services du noyau qui sont inutilisables pendant que l'interruption est prise en charge (voir ci-dessous pour savoir pourquoi).

En général, le seul objectif d'une routine d'interruption est de faire en sorte que le périphérique cesse d'interrompre et mette en file d'attente quelque chose à un niveau d'interruption inférieur (sous Unix, il s'agit généralement d'un niveau de non-interruption, mais sous Windows, il s'agit d'un niveau de répartition, d'apc ou de passif) afin de faire le gros du travail et d'avoir accès à davantage de fonctionnalités du noyau/os. Voir - Mise en œuvre d'un gestionnaire .

C'est une propriété de la façon dont les O/S doivent fonctionner, pas quelque chose d'inhérent à Linux. Une routine d'interruption peut s'exécuter à n'importe quel moment, donc l'état de ce que vous avez interrompu est incohérent. Si vous avez interrompu le code de planification des threads, son état est incohérent et vous ne pouvez pas être sûr de pouvoir "dormir" et changer de thread. Même si vous protégez le code de commutation de threads contre les interruptions, la commutation de threads est une fonctionnalité de très haut niveau du système d'exploitation et si vous protégez tout ce sur quoi elle repose, une interruption devient plus une suggestion que l'impératif impliqué par son nom.

0 votes

Que voulez-vous dire par l'arrêt de l'infrastructure de commutation des fils ? Est-ce juste une connaissance théorique ou pouvez-vous me donner une référence à un code réel dans le noyau qui fait cela pour soutenir votre affirmation ?

0 votes

C'est une vision théorique de ce qu'est une interruption - logiquement, si vous dormez, cela ne vous profite que si vous pouvez changer de fil, mais vous ne pouvez pas. Et si vous le faisiez, le système entier se bloquerait de toute façon parce que vous ne pouvez pas aller très loin sans toucher un service qui ne peut pas fonctionner. Si vous pouvez interrompre le système de paging à n'importe quel moment, pourquoi pensez-vous qu'il pourrait être réintroduit et continuer à fonctionner ? Il serait presque impossible de coder un o/s si cela était nécessaire.

0 votes

Par arrêt, je veux dire qu'il ne peut pas fonctionner - le quantum d'exécution ne peut jamais expirer et un nouveau thread ne sera jamais programmé tant que vous assurez le service de l'interruption.

3voto

Andres Jaan Tack Points 9929

Alors qu'est-ce qui empêche le scehduler de mettre le contexte d'interruption en veille et de prendre le prochain processus planifiable et de lui passer le contrôle ?

L'ordonnancement se fait sur des interruptions de minuterie. La règle de base est qu'une seule interruption peut être ouverte à la fois, donc si vous vous endormez pendant l'interruption "obtention de données du périphérique X", l'interruption de temporisation ne peut pas s'exécuter pour la planifier.

Les interruptions se produisent également plusieurs fois et se chevauchent. Si vous mettez en veille l'interruption "got data", et que vous recevez ensuite d'autres données, que se passe-t-il ? C'est suffisamment confus (et fragile) pour que la règle générale soit : pas de sommeil dans les interruptions. Vous le ferez mal.

1 votes

Je ne suis pas d'accord avec le fait que "la règle de base est une seule interruption". Une interruption peut être imbriquée. Veuillez vous référer à bovet cesati, chapitre 4.3, "Nested execution of Exception and Interrupt Handlers".

0 votes

Vous avez un bon point, mais notez le paragraphe suivant (ils peuvent se chevaucher, ce que vous appelez imbriqué). C'est une règle "de base" car si vous faites autre chose, il vaut mieux savoir ce qui se passe.

2voto

Ryan Fox Points 5181

Même si vous pouviez mettre une ISR en sommeil, vous ne voudriez pas le faire. Vous voulez que vos ISRs soient aussi rapides que possible pour réduire le risque de manquer les interruptions suivantes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X