Parfois, chaque fois que j'écris un programme sous Linux et qu'il plante à cause d'un bogue quelconque, il devient un processus ininterrompu et continue de fonctionner pour toujours jusqu'à ce que je redémarre mon ordinateur (même si je me déconnecte). Mes questions sont:
- Qu'est-ce qui fait qu'un processus devient ininterrompu?
- Comment puis-je empêcher cela de se produire?
- C'est probablement une question stupide, mais y a-t-il un moyen de l'interrompre sans redémarrer mon ordinateur?
linux
scheduling
preemption
Jason Baker
la source
la source
TASK_UNINTERUPTIBLE
état chaque fois que le système n'est pas dans un état inactif, collectant ainsi de force des données, attendant de transmettre une fois que le super utilisateur quitte? Ce serait une mine d'or pour les pirates informatiques pour récupérer des informations, revenir à l'état de zombie et transmettre des informations via le réseau au repos. Certains peuvent soutenir que c'est une façon de créer unBlackdoor
pour les pouvoirs en place, d'entrer et de sortir de n'importe quel système comme souhaité. Je crois fermement que cette faille peut être scellée pour de bon, en éliminant le `TASK_UNINTERUPTIBRéponses:
Un processus sans interruption est un processus qui se trouve dans un appel système (fonction noyau) qui ne peut pas être interrompu par un signal.
Pour comprendre ce que cela signifie, vous devez comprendre le concept d'appel système interruptible. L'exemple classique est
read()
. Il s'agit d'un appel système qui peut prendre beaucoup de temps (secondes) car il peut potentiellement impliquer la mise en marche d'un disque dur ou le déplacement de têtes. Pendant la plupart de ce temps, le processus sera en veille, bloquant 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), puis ce qui suit se produit:
Le retour prématuré 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 peuvent pas être interrompus de cette manière. Si le système se bloque pour une raison quelconque, le processus peut rester indéfiniment dans cet état impossible à tuer.
LWN a publié un bel article sur ce sujet en juillet.
Pour répondre à la question initiale:
Comment éviter que cela ne se produise: déterminez quel pilote 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 quelque sorte terminer l'appel système. Souvent, la manière la plus efficace de le faire sans toucher l'interrupteur d'alimentation est de tirer sur le cordon d'alimentation. Vous pouvez également devenir un hacker du noyau et faire en sorte que le pilote utilise TASK_KILLABLE, comme expliqué dans l'article LWN.
la source
Lorsqu'un processus est en mode utilisateur, il peut être interrompu à tout moment (passage en mode noyau). Lorsque le noyau retourne en mode utilisateur, il vérifie s'il y a des signaux en attente (y compris ceux qui sont utilisés pour tuer le processus, tels que
SIGTERM
etSIGKILL
). Cela signifie qu'un processus ne peut être tué qu'au 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, tuer un thread peut potentiellement corrompre les structures de données utilisées par d'autres threads dans le même processus) .
Lorsque le noyau a besoin de faire quelque chose qui pourrait prendre beaucoup de temps (attendre sur un tube écrit par un autre processus ou attendre que le matériel fasse quelque chose, par exemple), il dort en se marquant comme endormi et en appelant le planificateur pour passer à un autre processus (s'il n'y a pas de processus non dormant, il passe à un processus "factice" qui indique au processeur de ralentir un peu et se place dans une boucle - la boucle inactive).
Si un signal est envoyé à un processus en veille, il doit être réveillé avant de retourner dans l'espace utilisateur et de traiter ainsi le signal en attente. Ici, nous avons la différence entre les deux principaux types de sommeil:
TASK_INTERRUPTIBLE
, le sommeil interruptible. Si une tâche est marquée de cet indicateur, 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 et, après son réveil, le vérifiera et reviendra de l'appel système. Une fois le signal traité, l'appel système peut potentiellement être redémarré automatiquement (et je n'entrerai pas dans les détails sur la façon dont cela fonctionne).TASK_UNINTERRUPTIBLE
, le sommeil ininterrompu. 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. Cela peut également être utilisé pour les dortoirs connus pour être très courts.TASK_KILLABLE
(mentionné dans l'article LWN lié à la réponse de ddaa) est une nouvelle variante.Cela répond à votre première question. Quant à votre deuxième question: vous ne pouvez pas éviter les sommeil ininterrompus, c'est une chose normale (cela arrive, par exemple, chaque fois qu'un processus lit / écrit depuis / 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), où 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 se rétablisse; 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 raison pour laquelle le noyau attend le retour en mode utilisateur pour délivrer un signal ou tuer le processus: cela corromprait potentiellement les structures de données du noyau (le code en attente d'un sommeil interruptible peut recevoir une erreur qui le signale pour revenir à l'espace utilisateur, où le processus peut être tué; le code en attente d'un sommeil ininterrompu n'attend aucune erreur).
la source
Les processus ininterrompus attendent généralement des E / S suite à une erreur de page.
Considère ceci:
Le processus / la tâche ne peut pas être interrompu dans cet état, car il ne peut gérer aucun signal; si c'était le cas, une autre erreur de page se produirait et elle serait de retour là où elle était.
Quand je dis "processus", je veux vraiment dire "tâche", qui sous Linux (2.6) se traduit approximativement par "thread" qui peut ou non avoir une entrée individuelle "thread group" dans / proc
Dans certains cas, cela peut attendre longtemps. Un exemple typique de ceci serait où le fichier exécutable ou mmap'd se trouve sur un système de fichiers réseau où le serveur a échoué. Si les E / S réussissent finalement, la tâche se poursuivra. Si elle échoue finalement, la tâche obtiendra généralement un SIGBUS ou quelque chose.
la source
À votre troisième question: je pense que vous pouvez tuer les processus ininterrompus en exécutant
sudo kill -HUP 1
. Il redémarrera init sans terminer les processus en cours et après l'avoir exécuté, mes processus ininterrompus avaient disparu.la source
Si vous parlez d'un processus "zombie" (qui est désigné comme "zombie" dans la sortie ps), il s'agit d'un enregistrement inoffensif dans la liste de processus en attente que quelqu'un récupère son code de retour et il pourrait être ignoré en toute sécurité.
Pourriez-vous s'il vous plaît décrire ce qu'est un «processus sans interruption» pour vous? Survit-il au "kill -9" et avance-t-il joyeusement? Si tel est le cas, alors il est bloqué sur un appel système, qui est bloqué dans un pilote, et vous êtes coincé avec ce processus jusqu'au redémarrage (et parfois il est préférable de redémarrer bientôt) ou au déchargement du pilote concerné (ce qui est peu probable) . Vous pouvez essayer d'utiliser "strace" pour savoir où votre processus est bloqué et l'éviter à l'avenir.
la source