web-dev-qa-db-fra.com

Etats de processus Linux

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

83
Blair

En attendant read() ou write() vers/depuis un retour de descripteur de fichier, le processus sera mis dans un type de veille spécial, appelé "D" ou "Veille disque". Ceci est spécial, car le processus ne peut être ni tué ni interrompu tant qu'il est dans un tel état. Un processus attendant un retour de ioctl () serait également mis en veille de cette manière.

Une exception à cela est lorsqu'un fichier (tel qu'un terminal ou un autre périphérique à caractère) est ouvert en mode O_NONBLOCK, Transmis lorsqu'il est supposé 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. De plus, je n’ai jamais essayé une ioctl() susceptible de bloquer sur un fd ouvert en mode non bloquant (du moins, pas en connaissance de cause).

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

Certains programmes d’espace utilisateur, dans certaines circonstances, restent dans cet état pour toujours, jusqu’à ce qu’ils soient redémarrés. 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.

80
Tim Post

Lorsqu'un processus doit 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 durer longtemps - au moins 5 ms. Le temps de recherche d'un disque est commun, et 5 ms vaut 10 millions Les cycles du processeur, une éternité du point de vue du programme!

Du point de vue du programmeur (également appelé "dans l'espace utilisateur"), cela s'appelle un appel système bloquant. Si vous appelez write(2) (qui est un fin wrapper 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, cela va jusqu'à un pilote de contrôleur de disque spécifique (nom de fichier → système de fichiers/VFS → périphérique bloc → pilote de périphérique), où une commande permettant d'extraire un bloc sur disque est soumise au matériel approprié, ce qui est très difficile. opération rapide la plupart du temps.

ALORS le processus est mis en état de veille (dans l'espace du noyau, le blocage est appelé veille - 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, le appel système bloquant ​​est retourné avec le statut et les données appropriés et le flux du programme se poursuit.

Il est possible d'appeler la plupart des appels système d'E/S en mode non bloquant ​​(voir O_NONBLOCK Dans open(2) et fcntl(2)). Dans ce cas, les appels système sont renvoyés immédiatement et ne signalent que la soumission de l’opération sur disque. Le programmeur devra explicitement vérifier ultérieurement si l'opération a abouti, avec succès ou non, et extraire son résultat (par exemple, avec select(2)). C'est ce qu'on appelle la programmation asynchrone ou événementielle.

La plupart des réponses mentionnant D state (appelé TASK_UNINTERRUPTIBLE Dans 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 d'espace du noyau, lorsque ce chemin de code ne peut pas être interrompu (car ce serait trop complexe à programmer), dans l’espoir qu’il ne bloquerait que pendant très peu de temps. Je crois que la plupart des "états D" sont en réalité invisibles; ils ont une durée de vie très courte et ne peuvent pas être observés à l'aide d'outils d'échantillonnage tels que "top".

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

123
zerodeux

Un processus effectuant des E/S sera placé dans état D (veille ininterrompue) , ce qui libère la CPU jusqu'à ce qu'il y ait une interruption matérielle qui en avertit la CPU. retour à l'exécution du programme. Voir man ps pour les autres états du processus.

En fonction de votre noyau, il existe un planificateur de processus , qui assure le suivi d'une file d'attente de processus prête à être exécutée. Avec un algorithme de planification, il indique au noyau quel processus attribuer à quelle CPU. Il y a des processus de noyau et des processus d'utilisateur à considérer. Chaque processus se voit attribuer une tranche de temps, qui correspond à un bloc de temps CPU qu'il est autorisé à utiliser. Une fois que le processus utilise l'intégralité de sa tranche de temps, il est marqué comme étant arrivé à expiration et reçoit une priorité inférieure dans l'algorithme de planification.

Dans le noyau 2.6 , il existe un planificateur de complexité O (1) , quel que soit le nombre de processus en cours d'exécution, les CPU seront assignés en temps constant. C’est plus compliqué cependant, puisque la 2.6 introduisant la préemption et l’équilibrage de la charge de la CPU ne constitue pas un algorithme facile. Dans tous les cas, c’est efficace et les processeurs ne resteront pas inactifs pendant que vous attendez l’entrée/sortie.

7
user224579

Comme déjà expliqué par d’autres, les processus à l’état "D" (sommeil ininterruptible) sont responsables du blocage du processus ps. Cela m'est souvent arrivé à RedHat 6.x et aux répertoires de départ NFS auto-montés.

Pour lister les processus en é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, éventuellement, 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 constaté que le fait de donner la commande umount avec le commutateur -f (force) au système de fichiers nfs associé, permettait de réactiver 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 connexe s'est réveillé et j'ai pu résoudre le problème sans redémarrer.

2

Oui, la tâche est bloquée dans l'appel système read (). Une autre tâche prête est exécutée ou, si aucune autre tâche n'est prête, la tâche inactive (pour ce CPU) est exécutée.

Une lecture de disque bloquante normale entraîne le passage de la tâche à 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, notamment les terminaux et le réseau, ne se comportent pas exactement de la même manière: le processus se termine dans l'état "S", peut être interrompu et ne compte pas dans la moyenne de charge.

1
MarkR

En supposant que votre processus ne comporte qu'un seul thread et que vous utilisez des E/S bloquantes, votre processus bloquera l'attente de la fin des E/S. Le noyau choisira un autre processus à exécuter dans l'intervalle 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 en attente de finalisation des E/S s'affichent généralement à l'état D dans, par exemple, ps et top.

1
derobert

Oui, les tâches en attente de IO 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 .

0
Martin v. Löwis

Généralement, le processus va bloquer. Si l'opération de lecture est sur un descripteur de fichier marqué comme non bloquant ou si le processus utilise asynchrone IO il ne bloquera pas. En outre, si le processus comporte d'autres threads qui ne sont pas bloqués, ils peut continuer à courir.

La décision quant au prochain processus s'exécutant appartient au ordonnanceur du noyau.

0
Benno