Question

Parfois, chaque fois que j'écris un programme sous Linux et qu'il se bloque à cause d'un bogue, ce processus devient ininterruptible et continue de s'exécuter indéfiniment jusqu'à ce que je redémarre mon ordinateur (même si je me déconnecte). Mes questions sont:

  • Qu'est-ce qui rend un processus ininterrompu?
  • Comment puis-je empêcher cela?
  • C’est probablement une question idiote, mais y at-il un moyen de l’interrompre sans redémarrer mon ordinateur?
Était-ce utile?

La solution

Un processus ininterruptible est un processus qui se trouve être dans un appel système (fonction du noyau) qui ne peut pas être interrompu par un signal.

Pour comprendre ce que cela signifie, vous devez comprendre le concept d'un appel système pouvant être interrompu. L'exemple classique est read () . Il s’agit d’un appel système qui peut prendre un certain temps (en secondes) car il peut éventuellement impliquer de faire tourner un disque dur ou de déplacer des têtes. Pendant la majeure partie de cette période, le processus sera en veille et bloquera le matériel.

Pendant que le processus est en veille dans l'appel système, il peut recevoir un signal asynchrone Unix (par exemple, SIGTERM). Les événements suivants se produisent:

  • Les appels système se terminent prématurément et sont configurés pour renvoyer -EINTR à l'espace utilisateur.
  • Le gestionnaire de signaux est exécuté.
  • Si le processus est toujours en cours d'exécution, il récupère la valeur de retour de l'appel système et peut effectuer le même appel à nouveau.

Le renvoi anticipé de l'appel système permet au code d'espace utilisateur de modifier immédiatement son comportement en réponse au signal. Par exemple, terminer proprement en réaction à SIGINT ou à SIGTERM.

D'autre part, certains appels système ne sont pas autorisés à être interrompus de cette manière. Si le système appelle un blocage pour une raison quelconque, le processus peut rester indéfiniment dans cet état impossible à tuer.

LWN a publié un article intéressant sur ce sujet en juillet.

Pour répondre à la question initiale:

  • Comment éviter cela: déterminez le pilote qui vous cause des problèmes, arrêtez d’utiliser ou devenez un hacker du noyau et corrigez-le.

  • Comment tuer un processus sans interruption sans redémarrer: faites en sorte que l'appel système se termine. Le moyen le plus efficace de le faire sans appuyer sur l'interrupteur consiste à tirer sur le cordon d'alimentation. Vous pouvez également devenir un pirate du noyau et obliger le pilote à utiliser TASK_KILLABLE, comme expliqué dans l'article de LWN.

Autres conseils

Lorsqu'un processus est en mode utilisateur, il peut être interrompu à tout moment (passage en mode noyau). Lorsque le noyau revient au mode utilisateur, il vérifie si des signaux sont en attente (y compris ceux utilisés pour tuer le processus, tels que SIGTERM et SIGKILL ). Cela signifie qu'un processus peut être tué uniquement lors du retour en mode utilisateur.

La raison pour laquelle un processus ne peut pas être tué en mode noyau est qu’il pourrait potentiellement corrompre les structures du noyau utilisées par tous les autres processus de la même machine (de la même manière que tuer un thread peut potentiellement corrompre les structures de données utilisées par d’autres threads du même ordinateur). même processus).

Lorsque le noyau doit faire quelque chose qui peut prendre longtemps (attendre un tuyau écrit par un autre processus ou attendre que le matériel fasse quelque chose, par exemple), il dort en se signalant qu'il est en veille et en appelant le planificateur. passer à un autre processus (s'il n'y a pas de processus non en veille, il bascule vers un processus "factice" qui indique au processeur de ralentir un peu et de rester en boucle - la boucle inactive).

Si un signal est envoyé à un processus en veille, il doit être réveillé avant qu'il ne retourne dans l'espace utilisateur et traite ainsi le signal en attente. Nous avons ici la différence entre les deux principaux types de sommeil:

  • TASK_INTERRUPTIBLE , le sommeil interruptible. Si une tâche est marquée avec ce drapeau, elle est en veille, mais peut être réveillée par des signaux. Cela signifie que le code qui a marqué la tâche comme étant en veille attend un signal possible. Après son réveil, il le recherchera et reviendra de l'appel système. Une fois le signal traité, l’appel système peut potentiellement être automatiquement redémarré (et je n’entrerai pas dans les détails à ce sujet.)
  • TASK_UNINTERRUPTIBLE , le sommeil ininterruptible. Si une tâche est marquée avec cet indicateur, elle ne s'attend pas à être réveillée par autre chose que ce qu'elle attend, soit parce qu'elle ne peut pas être redémarrée facilement, soit parce que les programmes s'attendent à ce que l'appel système soit atomique. Ceci peut également être utilisé pour des nuits connues pour être très courtes.

TASK_KILLABLE (mentionné dans l'article de LWN associé à la réponse de ddaa) est une nouvelle variante.

Ceci répond à votre première question. En ce qui concerne votre deuxième question: vous ne pouvez pas éviter les sommeil ininterruptible, ils sont une chose normale (cela se produit, par exemple, chaque fois qu'un processus lit / écrit à partir de / sur le disque); Cependant, ils ne devraient durer qu'une fraction de seconde. S'ils durent beaucoup plus longtemps, cela signifie généralement un problème matériel (ou un problème de pilote de périphérique qui ressemble au noyau), le pilote de périphérique attend que le matériel fasse quelque chose qui ne se produira jamais. Cela peut également signifier que vous utilisez NFS et que le serveur NFS est en panne (il attend que le serveur soit restauré; vous pouvez également utiliser l'option "intr" pour éviter le problème).

Enfin, la raison pour laquelle vous ne pouvez pas récupérer est la même que le noyau attend jusqu'à ce qu'il revienne en mode utilisateur pour envoyer un signal ou interrompre le processus: cela risquerait de corrompre les structures de données du noyau (le code en attente de sommeil interruptible peut recevoir une erreur qui lui dit de retourner dans l’espace utilisateur, où le processus peut être tué; le code en attente de sommeil ininterruptible n’attend pas d’erreur)

Les processus ininterrompus attendent habituellement des E / S suite à une erreur de page.

Considérez ceci:

  • Le thread tente d'accéder à une page non centrale (un exécutable chargé à la demande, une page de mémoire anonyme remplacée ou un fichier mmap () 'd chargé à la demande, qui sont à peu près la même chose)
  • Le noyau est en train de (le charger) dans
  • Le processus ne peut pas continuer tant que la page n'est pas disponible.

Le processus / la tâche ne peut pas être interrompu dans cet état car il ne peut gérer aucun signal; si cela se produisait, une autre faute de page se produirait et ce serait le retour.

Quand je dis "processus", je veux vraiment dire "tâche", ce qui sous Linux (2.6) se traduit approximativement par "thread". qui peut ou non avoir un "groupe de threads" individuel entrée dans / proc

Dans certains cas, l'attente peut être longue. Un exemple typique de ceci serait où le fichier exécutable ou mmap'd est sur un système de fichiers réseau où le serveur a échoué. Si les E / S réussissent, la tâche se poursuit. Si cela échoue, la tâche obtiendra généralement un SIGBUS ou quelque chose du genre.

À votre troisième question: Je pense que vous pouvez tuer les processus sans interruption en exécutant sudo kill -HUP 1 . Il redémarrera init sans mettre fin aux processus en cours. Après l'avoir exécuté, mes processus ininterrompus ont disparu.

Si vous parlez d'un " zombie " processus (qui est désigné comme "zombie" dans la sortie ps), il s’agit d’un enregistrement inoffensif dans la liste des processus qui attend que quelqu'un récupère son code retour et qui pourrait être ignoré en toute sécurité.

Pourriez-vous décrire le processus et le "processus ininterruptible"? est pour toi? T-il survivre à la "& kill; kill -9"? et heureusement avance? Si tel est le cas, alors il est bloqué sur un appel système, qui est bloqué dans un pilote, et vous êtes bloqué par ce processus jusqu'au redémarrage (et parfois, il est préférable de redémarrer rapidement) ou de décharger le pilote approprié (ce qui est peu probable). . Vous pouvez essayer d'utiliser "strace". pour savoir où votre processus est bloqué et l'éviter à l'avenir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top