États du processus Linux

89

Sous Linux, qu'arrive-t-il à l'état d'un processus lorsqu'il a besoin de lire des blocs à partir d'un disque? Est-ce bloqué? Si oui, comment un autre processus est-il choisi pour s'exécuter?

Blair
la source

Réponses:

86

En attendant read()ou write()vers / depuis un retour de descripteur de fichier, le processus sera placé dans un type spécial de sommeil, appelé «D» ou «Disk Sleep». Ceci est spécial, car le processus ne peut pas être tué ou interrompu dans un tel état. Un processus en attente d'un retour de ioctl () serait également mis en veille de cette manière.

Une exception à ceci est quand un fichier (tel qu'un terminal ou un autre périphérique de caractères) est ouvert en O_NONBLOCKmode, passé quand il suppose qu'un périphérique (tel qu'un modem) aura besoin de temps pour s'initialiser. Cependant, vous avez indiqué bloquer les périphériques dans votre question. Aussi, je n'ai jamais essayé un ioctl()qui est susceptible de bloquer sur un fd ouvert en mode non bloquant (du moins pas sciemment).

La façon dont un autre processus est choisi dépend entièrement du planificateur que vous utilisez, ainsi que de ce que d'autres processus auraient pu faire pour modifier leurs poids dans ce planificateur.

Certains programmes d'espace utilisateur dans certaines circonstances sont connus pour rester dans cet état pour toujours, jusqu'à leur redémarrage. Ceux-ci sont généralement regroupés avec d'autres «zombies», mais le terme ne serait pas correct car ils ne sont pas techniquement périmés.

Tim Post
la source
1
"Un processus en attente d'un retour de ioctl () serait également mis en veille de cette manière". Je viens de tuer le processus de mon espace utilisateur en attente d'un IOCTL bloquant donc ce n'est pas vrai. Sauf si je ne comprends pas bien
Hamzahfrq
Il serait extrêmement difficile de chronométrer un tel test. Les processus ininterrompus ne peuvent pas être tués; si vous pouviez le tuer, alors il bloquait simplement (le noyau n'était au milieu d'aucune partie de l'ioctl, et copiait toute réponse correspondante dans l'espace utilisateur à l'emplacement que vous avez passé (ou du moins n'était pas dans le au milieu de la copie)). Linux a également beaucoup changé depuis 2009, date à laquelle cela a été écrit; le phénomène est beaucoup moins observable qu'il ne l'était autrefois.
Tim Post
133

Lorsqu'un processus a besoin d'extraire des données d'un disque, il arrête effectivement de s'exécuter sur le processeur pour permettre à d'autres processus de s'exécuter car l'opération peut prendre beaucoup de temps - au moins 5 ms de temps de recherche pour un disque sont courants, et 5 ms équivaut à 10 millions Cycles CPU, une éternité du point de vue du programme!

Du point de vue du programmeur (également dit "dans l'espace utilisateur"), cela s'appelle un appel système bloquant . Si vous appelez write(2)(qui est un fin wrapper de libc autour de l'appel système du même nom), votre processus ne s'arrête pas exactement à cette limite; il continue, dans le noyau, à exécuter le code d'appel système. La plupart du temps, il va jusqu'à un pilote de contrôleur de disque spécifique (nom de fichier → système de fichiers / VFS → périphérique de bloc → pilote de périphérique), où une commande pour récupérer un bloc sur le disque est soumise au matériel approprié, ce qui est très fonctionnement rapide la plupart du temps.

ALORS le processus est mis en état de veille (dans l'espace noyau, le blocage est appelé endormi - rien n'est jamais «bloqué» du point de vue du noyau). Il sera réveillé une fois que le matériel aura finalement récupéré les données appropriées, puis le processus sera marqué comme exécutable et sera planifié. Finalement, le planificateur exécutera le processus.

Enfin, dans l'espace utilisateur, l' appel système de blocage retourne avec le statut et les données appropriés, et le déroulement du programme se poursuit.

Il est possible d'appeler la plupart des appels système d'E / S en mode non bloquant (voir O_NONBLOCKdans open(2)et fcntl(2)). Dans ce cas, les appels système retournent immédiatement et signalent uniquement la soumission de l'opération de disque. Le programmeur devra vérifier explicitement ultérieurement si l'opération s'est terminée, avec succès ou non, et récupérer son résultat (par exemple, avec select(2)). C'est ce qu'on appelle la programmation asynchrone ou basée sur les événements.

La plupart des réponses ici mentionnant l' état D (qui est appelé TASK_UNINTERRUPTIBLEdans les noms d'état Linux) sont incorrectes. L' état D est un mode de veille spécial qui n'est déclenché que dans un chemin de code de l'espace noyau, lorsque ce chemin de code ne peut pas être interrompu (car il serait trop complexe à programmer), dans l'espoir qu'il ne bloquerait que pour un très court instant. Je crois que la plupart des "états D" sont en fait invisibles; ils sont de très courte durée et ne peuvent pas être observés par des outils d'échantillonnage tels que «top».

Vous pouvez rencontrer des processus impossibles à tuer à l'état D dans quelques situations. NFS est célèbre pour cela, et je l'ai rencontré plusieurs fois. Je pense qu'il y a un conflit sémantique entre certains chemins de code VFS, qui supposent toujours atteindre les disques locaux et une détection rapide des erreurs (sur SATA, un délai d'attente d'erreur serait d'environ 100 ms), et NFS, qui récupère en fait les données du réseau qui est plus résilient et a une récupération lente (un délai TCP de 300 secondes est courant). Lisez cet article pour la solution cool introduite dans Linux 2.6.25 avec l' TASK_KILLABLEétat. Avant cette ère, il y avait un hack où vous pouviez envoyer des signaux aux clients de processus NFS en envoyant un SIGKILL au thread du noyau rpciod, mais oubliez cette vilaine astuce.…

zerodeux
la source
2
+1 pour la réponse détaillée, mais veuillez noter que ce fil a une réponse acceptée depuis près de deux ans. Cliquez sur le lien "Questions" si vous souhaitez donner un coup de main sur des questions plus récentes. Bienvenue dans Stack Overflow et merci de votre contribution!
GargantuChet
20
Cette réponse est la seule à mentionner NFS, qui dans certains environnements est l'explication la plus courante des processus à l'état D. +1.
Pinko
14
Très bonne réponse, merci. Notez également que le processus passe à l'état D en attendant les pages qui ont été permutées, de sorte qu'un processus de battage restera dans l'état D pendant un long moment.
cha0site
@zerodeux bonne réponse, mais je pense que votre schéma (nom de fichier -> système de fichiers / VFS -> bloquer le périphérique -> pilote de périphérique) il devrait être (nom de fichier -> VFS -> système de fichiers (ext3) -> bloquer le périphérique -> pilote de périphérique)
c4f4t0r
1
Serait-il prudent de supposer que le temps passé dans le noyau à attendre les verrous rotatifs (qui peuvent ou non être liés aux entrées / sorties du disque) est tous signalé comme état D dans /proc/stat?
mèche
8

Un processus effectuant des E / S sera mis à l' état D (veille ininterrompue) , ce qui libère le CPU jusqu'à ce qu'il y ait une interruption matérielle qui indique au CPU de reprendre l'exécution du programme. Voir man pspour les autres états de processus.

En fonction de votre noyau, il existe un planificateur de processus , qui assure le suivi d'une file d'attente de processus prêts à être exécutés. Il, avec un algorithme de planification, indique au noyau quel processus affecter à quel CPU. Il y a des processus du noyau et des processus utilisateur à prendre en compte. Chaque processus se voit attribuer une tranche de temps, qui est une partie du temps CPU qu'il est autorisé à utiliser. Une fois que le processus utilise toute sa tranche de temps, il est marqué comme expiré et reçoit une priorité inférieure dans l'algorithme de planification.

Dans le noyau 2.6 , il existe un planificateur de complexité temporelle O (1) , donc quel que soit le nombre de processus en cours d'exécution, il attribuera des processeurs en temps constant. C'est plus compliqué cependant, puisque 2.6 a introduit la préemption et que l'équilibrage de la charge du processeur n'est pas un algorithme facile. Dans tous les cas, c'est efficace et les CPU ne resteront pas inactifs pendant que vous attendez les E / S.

user224579
la source
3

Comme déjà expliqué par d'autres, les processus à l'état "D" (sommeil ininterrompu) sont responsables du blocage du processus ps. Pour moi, cela s'est produit à plusieurs reprises avec RedHat 6.x et les répertoires personnels NFS montés automatiquement.

Pour répertorier les processus à l'état D, vous pouvez utiliser les commandes suivantes:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

Pour connaître le répertoire actuel du processus et, peut-être, le disque NFS monté qui présente des problèmes, vous pouvez utiliser une commande similaire à l'exemple suivant (remplacez 31134 par le numéro du processus en veille):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

J'ai trouvé que donner la commande umount avec le commutateur -f (force), au système de fichiers nfs monté associé, était capable de réveiller le processus de veille:

umount -f /auto/pippo

le système de fichiers n'a pas été démonté, car il était occupé, mais le processus associé s'est réveillé et j'ai pu résoudre le problème sans redémarrer.

Valerio Di Giampietro
la source
1

En supposant que votre processus est un seul thread et que vous utilisez des E / S bloquantes, votre processus se bloquera en attendant la fin des E / S. Le noyau choisira un autre processus à exécuter entre-temps en fonction de la gentillesse, de la priorité, de la dernière exécution, etc. S'il n'y a pas d'autres processus exécutables, le noyau n'en exécutera aucun; au lieu de cela, il indiquera au matériel que la machine est inactive (ce qui réduira la consommation d'énergie).

Les processus qui attendent la fin des E / S apparaissent généralement dans l'état D dans, par exemple, pset top.

derobert
la source
J'ai lancé plusieurs processus en utilisant environ 10% de la mémoire totale. J'ai remarqué que beaucoup d'entre eux sont à l'état D. Est-ce dû à une IO lente sur cette machine particulière? Disons que j'ai 9 processus, ils peuvent être en compétition pour IO et beaucoup d'entre eux sont à l'état D.
Kemin Zhou
@KeminZhou Comparé à la vitesse du processeur, les E / S sont assez lentes, même rapides. Un seul processus lourd d'E / S peut facilement occuper un disque magnétique, même un SSD. 10 processus lourds d'E / S peuvent en occuper un bon nombre.
derobert
1

Oui, la tâche est bloquée lors de l'appel système read (). Une autre tâche qui est prête s'exécute, ou si aucune autre tâche n'est prête, la tâche inactive (pour cette CPU) s'exécute.

Une lecture de disque normale et bloquante amène la tâche à entrer dans l'état "D" (comme d'autres l'ont noté). Ces tâches contribuent à la charge moyenne, même si elles ne consomment pas le processeur.

Certains autres types d'E / S, en particulier ttys et réseau, ne se comportent pas tout à fait de la même manière - le processus se retrouve à l'état "S" et peut être interrompu et ne compte pas dans la moyenne de charge.

MarkR
la source
0

Oui, les tâches en attente d'E / S sont bloquées et d'autres tâches sont exécutées. La sélection de la tâche suivante est effectuée par le planificateur Linux .

Martin c.Löwis
la source
0

Généralement, le processus se bloque. Si l'opération de lecture est sur un descripteur de fichier marqué comme non bloquant ou si le processus utilise des E / S asynchrones, il ne bloquera pas. De plus, si le processus a d'autres threads qui ne sont pas bloqués, ils peuvent continuer à s'exécuter.

La décision quant au processus qui s'exécute ensuite appartient au planificateur dans le noyau.

Benno
la source