Stati del processo Linux


89

In Linux, cosa succede allo stato di un processo quando ha bisogno di leggere blocchi da un disco? È bloccato? In caso affermativo, come viene scelto di eseguire un altro processo?

Risposte:


86

Durante l'attesa read()o il write()ritorno di un descrittore di file, il processo verrà messo in un tipo speciale di sleep, noto come "D" o "Disk Sleep". Questo è speciale, perché il processo non può essere ucciso o interrotto mentre si trova in tale stato. Anche un processo in attesa di un ritorno da ioctl () verrebbe messo a riposo in questo modo.

Un'eccezione è quando un file (come un terminale o un altro dispositivo a caratteri) viene aperto in O_NONBLOCKmodalità, passato quando si presume che un dispositivo (come un modem) avrà bisogno di tempo per essere inizializzato. Tuttavia, hai indicato i dispositivi a blocchi nella tua domanda. Inoltre, non ho mai provato uno ioctl()che rischia di bloccare su un fd aperto in modalità non bloccante (almeno non consapevolmente).

Il modo in cui viene scelto un altro processo dipende interamente dallo scheduler che stai utilizzando, nonché da ciò che altri processi potrebbero aver fatto per modificare i loro pesi all'interno di quello scheduler.

Alcuni programmi in spazio utente in determinate circostanze sono noti per rimanere in questo stato per sempre, fino al riavvio. Questi sono tipicamente raggruppati con altri "zombi", ma il termine non sarebbe corretto in quanto non sono tecnicamente defunti.


1
"Un processo in attesa di un ritorno da ioctl () verrebbe messo a dormire in questo modo". Ho appena terminato il mio processo nello spazio utente in attesa di un IOCTL di blocco, quindi questo non è vero. A meno che non mi capisca male
Hamzahfrq

Sarebbe tremendamente difficile programmare un simile test. I processi ininterrotti non possono essere uccisi; se eri in grado di ucciderlo, allora stava semplicemente bloccando (il kernel non era nel mezzo di nessuna parte di ioctl e copiava qualsiasi risposta corrispondente allo spazio utente nella posizione che hai passato (o almeno non era nel metà della copia)). Anche Linux è cambiato molto dal 2009 quando è stato scritto; il fenomeno è molto meno osservabile di una volta.
Tim Post

133

Quando un processo ha bisogno di recuperare dati da un disco, interrompe effettivamente l'esecuzione sulla CPU per consentire l'esecuzione di altri processi perché l'operazione potrebbe richiedere molto tempo per essere completata: almeno 5 ms di tempo di ricerca per un disco è comune e 5 ms è 10 milioni Cicli della CPU, un'eternità dal punto di vista del programma!

Dal punto di vista del programmatore (detto anche "in userspace"), questa è chiamata chiamata di sistema di blocco . Se si chiama write(2)(che è un sottile wrapper libc attorno alla chiamata di sistema con lo stesso nome), il processo non si ferma esattamente a quel limite; continua, nel kernel, a eseguire il codice della chiamata di sistema. La maggior parte delle volte arriva fino a uno specifico driver del controller del disco (nome file → filesystem / VFS → dispositivo a blocchi → driver del dispositivo), dove un comando per recuperare un blocco su disco viene inviato all'hardware appropriato, il che è molto operazione veloce la maggior parte del tempo.

ALLORA il processo viene messo in stato di sospensione (nello spazio del kernel, il blocco è chiamato inattivo - nulla è mai "bloccato" dal punto di vista del kernel). Verrà attivato una volta che l'hardware avrà finalmente recuperato i dati corretti, quindi il processo verrà contrassegnato come eseguibile e verrà pianificato. Alla fine, lo scheduler eseguirà il processo.

Infine, nello spazio utente, la chiamata di sistema di blocco ritorna con lo stato e i dati corretti e il flusso del programma continua.

È possibile richiamare la maggior parte delle chiamate di sistema I / O in modalità non bloccante (vedere O_NONBLOCKin open(2)e fcntl(2)). In questo caso, le chiamate di sistema tornano immediatamente e segnalano solo l'invio dell'operazione del disco. Il programmatore dovrà verificare esplicitamente in un secondo momento se l'operazione è stata completata, con successo o meno, e recuperarne il risultato (es. Con select(2)). Questa è chiamata programmazione asincrona o basata su eventi.

La maggior parte delle risposte qui che menzionano lo stato D (che è chiamato TASK_UNINTERRUPTIBLEnei nomi degli stati di Linux) non sono corrette. Lo stato D è una modalità di sospensione speciale che viene attivata solo in un percorso del codice nello spazio del kernel, quando quel percorso del codice non può essere interrotto (perché sarebbe troppo complesso da programmare), con l'aspettativa che si blocchi solo per un poco tempo. Credo che la maggior parte degli "stati D" siano effettivamente invisibili; hanno vita molto breve e non possono essere osservati da strumenti di campionamento come "top".

È possibile incontrare processi inattuabili nello stato D in alcune situazioni. NFS è famoso per questo e l'ho incontrato molte volte. Penso che ci sia uno scontro semantico tra alcuni percorsi di codice VFS, che presumono di raggiungere sempre i dischi locali e il rilevamento rapido degli errori (su SATA, un timeout di errore sarebbe di circa 100 ms) e NFS, che in realtà recupera i dati dalla rete che è più resiliente e ha un recupero lento (un timeout TCP di 300 secondi è comune). Leggi questo articolo per la fantastica soluzione introdotta in Linux 2.6.25 con lo TASK_KILLABLEstato. Prima di questa era c'era un hack in cui si potevano effettivamente inviare segnali ai client di processo NFS inviando un SIGKILL al thread del kernel rpciod, ma dimenticatevi di quel brutto trucco ...


2
+1 per la risposta dettagliata, ma tieni presente che questo thread ha ricevuto una risposta accettata per quasi due anni. Clicca il link "Domande" se vuoi dare una mano su domande più recenti. Benvenuto in Stack Overflow e grazie per il contributo!
GargantuChet

20
Questa risposta è l'unica a menzionare NFS, che in alcuni ambienti è la spiegazione più comune per i processi nello stato D. +1.
Pinko

14
Risposta molto buona, grazie. Nota anche che il processo passa allo stato D mentre attende le pagine che sono state scambiate, quindi un processo di thrashing rimarrà nello stato D per molto tempo.
cha0site

@zerodeux buona risposta, ma penso che il tuo schema (nome file -> filesystem / VFS -> dispositivo a blocchi -> driver di dispositivo) dovrebbe essere (nome file -> VFS -> filesystem (ext3) -> dispositivo di blocco -> driver di dispositivo)
c4f4t0r

1
Sarebbe lecito ritenere che il tempo trascorso nel kernel in attesa di spinlock (che può o non può essere correlato all'i / o del disco) è stato riportato come D-state in /proc/stat?
stoppino

8

Un processo che esegue I / O verrà messo in stato D (uninterruptable sleep) , che libera la CPU fino a quando non si verifica un interrupt hardware che dice alla CPU di tornare all'esecuzione del programma. Vedere man psper gli altri stati del processo.

A seconda del kernel, esiste uno scheduler dei processi , che tiene traccia di una serie di processi pronti per l'esecuzione. Insieme a un algoritmo di pianificazione, dice al kernel quale processo assegnare a quale CPU. Ci sono processi del kernel e processi utente da considerare. A ogni processo viene assegnato un intervallo di tempo, che è un pezzo di tempo della CPU che è consentito utilizzare. Una volta che il processo utilizza tutto il suo intervallo di tempo, viene contrassegnato come scaduto e gli viene assegnata una priorità inferiore nell'algoritmo di pianificazione.

Nel kernel 2.6 , c'è uno scheduler di complessità temporale O (1) , quindi non importa quanti processi hai in esecuzione, assegnerà le CPU in tempo costante. Tuttavia è più complicato, dal momento che 2.6 ha introdotto la prelazione e il bilanciamento del carico della CPU non è un algoritmo facile. In ogni caso, è efficiente e le CPU non resteranno inattive durante l'attesa dell'I / O.


3

Come già spiegato da altri, i processi nello stato "D" (sleep uninterruptible) sono responsabili del blocco del processo ps. A me è successo molte volte con RedHat 6.x e directory home NFS montate automaticamente.

Per elencare i processi nello stato D puoi usare i seguenti comandi:

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

Per conoscere la directory corrente del processo e, potrebbe essere, il disco NFS montato che presenta problemi, è possibile utilizzare un comando simile al seguente esempio (sostituire 31134 con il numero del processo inattivo):

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

Ho scoperto che dando il comando umount con l'opzione -f (force), al relativo file system nfs montato, è stato possibile riattivare il processo inattivo:

umount -f /auto/pippo

il file system non è stato smontato, perché era occupato, ma il processo correlato si è attivato e sono stato in grado di risolvere il problema senza riavviare.


1

Supponendo che il processo sia un singolo thread e che si utilizzi l'I / O di blocco, il processo si bloccherà in attesa del completamento dell'I / O. Il kernel sceglierà un altro processo da eseguire nel frattempo in base alla gentilezza, priorità, ultimo tempo di esecuzione, ecc. Se non ci sono altri processi eseguibili, il kernel non ne eseguirà nessuno; invece, dirà all'hardware che la macchina è inattiva (il che si tradurrà in un minore consumo energetico).

I processi che sono in attesa del completamento dell'I / O in genere vengono visualizzati nello stato D in, ad esempio, pse top.


Ho avviato diversi processi utilizzando circa il 10% della memoria totale. Ho notato che molti di loro sono nello stato D. Ciò è dovuto a un IO lento su questa particolare macchina? Supponiamo che io abbia 9 processi, potrebbero essere in competizione per IO e molti di loro sono nello stato D.
Kemin Zhou

@KeminZhou Rispetto alle velocità della CPU, l'I / O è piuttosto lento, persino l'I / O veloce. Un singolo processo pesante di I / O può facilmente occupare un disco magnetico, anche un SSD. 10 processi pesanti di I / O potrebbero occuparne parecchi.
derobert

1

Sì, l'attività viene bloccata nella chiamata di sistema read (). Viene eseguita un'altra attività pronta o, se nessun'altra attività è pronta, viene eseguita l'attività inattiva (per quella CPU).

Una normale lettura del disco bloccante fa entrare l'attività nello stato "D" (come altri hanno notato). Tali attività contribuiscono al carico medio, anche se non consumano la CPU.

Alcuni altri tipi di I / O, in particolare tty e rete, non si comportano esattamente allo stesso modo: il processo finisce nello stato "S" e può essere interrotto e non conta per la media del carico.



0

Generalmente il processo si bloccherà. Se l'operazione di lettura è su un descrittore di file contrassegnato come non bloccante o se il processo utilizza IO asincrono, non verrà bloccato. Inoltre, se il processo ha altri thread che non sono bloccati, possono continuare a funzionare.

La decisione su quale processo eseguire dopo spetta allo scheduler nel kernel.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.