Estados del proceso de Linux

90

En Linux, ¿qué sucede con el estado de un proceso cuando necesita leer bloques de un disco? Esta bloqueado? Si es así, ¿cómo se elige ejecutar otro proceso?

Blair
fuente

Respuestas:

87

Mientras espera read()owrite() desde / hacia el retorno de un descriptor de archivo, el proceso se pondrá en un tipo especial de suspensión, conocido como "D" o "Disk Sleep". Esto es especial, porque el proceso no se puede matar ni interrumpir mientras se encuentra en tal estado. Un proceso que espera un retorno de ioctl () también se pondría en reposo de esta manera.

Una excepción a esto es cuando un archivo (como un terminal u otro dispositivo de caracteres) se abre en O_NONBLOCKmodo, pasado cuando se asume que un dispositivo (como un módem) necesitará tiempo para inicializarse. Sin embargo, indicó dispositivos de bloqueo en su pregunta. Además, nunca he probado un ioctl()que probablemente se bloquee en un fd abierto en modo sin bloqueo (al menos sin saberlo).

La forma en que se elige otro proceso depende completamente del programador que esté utilizando, así como de lo que otros procesos podrían haber hecho para modificar sus pesos dentro de ese programador.

Se sabe que algunos programas de espacio de usuario en determinadas circunstancias permanecen en este estado para siempre, hasta que se reinician. Por lo general, se agrupan con otros "zombis", pero el término no sería correcto ya que técnicamente no están extintos.

Tim Post
fuente
1
"Un proceso que espera un retorno de ioctl () también se pondría a dormir de esta manera". Acabo de matar mi proceso de espacio de usuario esperando un IOCTL de bloqueo, por lo que esto no es cierto. A menos que lo entienda mal
Hamzahfrq
Sería tremendamente difícil cronometrar tal prueba. Los procesos ininterrumpidos no se pueden eliminar; si pudo eliminarlo, entonces simplemente estaba bloqueando (el kernel no estaba en el medio de ninguna parte del ioctl, y copió cualquier respuesta correspondiente al espacio de usuario en la ubicación que pasó (o al menos no estaba en el en medio de la copia)). Linux también ha cambiado mucho desde 2009 cuando se escribió esto; el fenómeno es mucho menos observable que antes.
Tim Post
133

Cuando un proceso necesita obtener datos de un disco, efectivamente deja de ejecutarse en la CPU para permitir que otros procesos se ejecuten porque la operación puede tardar mucho en completarse; al menos 5ms de tiempo de búsqueda para un disco es común y 5ms son 10 millones Ciclos de CPU, ¡una eternidad desde el punto de vista del programa!

Desde el punto de vista del programador (también dicho "en el espacio de usuario"), esto se denomina llamada al sistema de bloqueo . Si llama write(2)(que es un envoltorio delgado de libc alrededor de la llamada al sistema del mismo nombre), su proceso no se detiene exactamente en ese límite; continúa, en el kernel, ejecutando el código de llamada del sistema. La mayoría de las veces llega hasta un controlador de controlador de disco específico (nombre de archivo → sistema de archivos / VFS → dispositivo de bloque → controlador de dispositivo), donde se envía un comando para buscar un bloque en el disco al hardware adecuado, que es muy operación rápida la mayor parte del tiempo.

ENTONCES, el proceso se pone en estado de suspensión (en el espacio del kernel, el bloqueo se llama dormir; nada se 'bloquea' desde el punto de vista del kernel). Se activará una vez que el hardware finalmente haya obtenido los datos adecuados, luego el proceso se marcará como ejecutable y se programará. Finalmente, el programador ejecutará el proceso.

Finalmente, en el espacio de usuario, la llamada al sistema de bloqueo regresa con el estado y los datos adecuados, y el flujo del programa continúa.

Es posible invocar la mayoría de las llamadas al sistema de E / S en modo sin bloqueo (ver O_NONBLOCKen open(2)y fcntl(2)). En este caso, las llamadas al sistema regresan inmediatamente y solo informan que se envía la operación del disco. El programador tendrá que verificar explícitamente en un momento posterior si la operación se completó, con éxito o no, y buscar su resultado (por ejemplo, con select(2)). Esto se llama programación asincrónica o basada en eventos.

La mayoría de las respuestas aquí que mencionan el estado D (que se llama TASK_UNINTERRUPTIBLEen los nombres de estado de Linux) son incorrectas. El estado D es un modo de suspensión especial que solo se activa en una ruta de código de espacio del kernel, cuando esa ruta de código no se puede interrumpir (porque sería demasiado complejo de programar), con la expectativa de que se bloquearía solo por un tiempo muy largo. poco tiempo. Creo que la mayoría de los "estados D" son en realidad invisibles; tienen una vida muy corta y no se pueden observar con herramientas de muestreo como 'top'.

Puede encontrar procesos que no se pueden matar en el estado D en algunas situaciones. NFS es famoso por eso y lo he encontrado muchas veces. Creo que hay un choque semántico entre algunas rutas de código VFS, que asumen que siempre llegan a los discos locales y la detección rápida de errores (en SATA, un tiempo de espera de error sería de unos 100 ms), y NFS, que en realidad obtiene datos de la red que es más resistente y tiene una recuperación lenta (un tiempo de espera de TCP de 300 segundos es común). Lea este artículo para conocer la excelente solución introducida en Linux 2.6.25 con el TASK_KILLABLEestado. Antes de esta era, había un truco en el que se podían enviar señales a los clientes de procesos NFS enviando un SIGKILL al hilo del kernel rpciod, pero olvídate de ese truco feo ...

zerodeux
fuente
2
+1 para la respuesta detallada, pero tenga en cuenta que este hilo ha tenido una respuesta aceptada durante casi dos años. Haga clic en el enlace "Preguntas" si desea echar una mano sobre preguntas más recientes. Bienvenido a Stack Overflow y gracias por contribuir.
GargantuChet
20
Esta respuesta es la única que menciona NFS, que en algunos entornos es la explicación más común para los procesos en el estado D. +1.
Pinko
14
Muy buena respuesta, gracias. También tenga en cuenta que el proceso pasa al estado D mientras espera las páginas que se han intercambiado, por lo que un proceso de eliminación estará en el estado D durante mucho tiempo.
Cha0site
@zerodeux buena respuesta, pero creo que su esquema (nombre de archivo -> sistema de archivos / VFS -> dispositivo de bloque -> controlador de dispositivo) debería ser (nombre de archivo -> VFS -> sistema de archivos (ext3) -> dispositivo de bloque -> controlador de dispositivo)
c4f4t0r
1
¿Sería seguro asumir que el tiempo pasado en el kernel esperando en los spinlocks (que pueden o no estar relacionados con la e / s del disco) se informa como estado D en /proc/stat?
mecha
8

Un proceso que realiza E / S se pondrá en estado D (suspensión ininterrumpida) , lo que libera la CPU hasta que se produce una interrupción de hardware que le indica a la CPU que vuelva a ejecutar el programa. Consulte man pslos otros estados del proceso.

Dependiendo de su kernel, hay un programador de procesos , que realiza un seguimiento de una cola de ejecución de procesos listos para ejecutarse. Junto con un algoritmo de programación, le dice al kernel qué proceso asignar a qué CPU. Hay procesos de kernel y procesos de usuario a considerar. A cada proceso se le asigna un intervalo de tiempo, que es una parte del tiempo de CPU que se le permite usar. Una vez que el proceso utiliza todo su intervalo de tiempo, se marca como vencido y se le da menor prioridad en el algoritmo de programación.

En el kernel 2.6 , hay un programador de complejidad de tiempo O (1) , por lo que no importa cuántos procesos tenga en ejecución, asignará CPU en tiempo constante. Sin embargo, es más complicado, ya que 2.6 introdujo la preferencia y el equilibrio de carga de la CPU no es un algoritmo fácil. En cualquier caso, es eficiente y las CPU no permanecerán inactivas mientras espera la E / S.

usuario224579
fuente
3

Como ya han explicado otros, los procesos en estado "D" (suspensión ininterrumpida) son responsables del bloqueo del proceso ps. A mí me ha sucedido muchas veces con RedHat 6.xy los directorios de inicio NFS montados automáticamente.

Para listar procesos en estado D puede usar los siguientes comandos:

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

Para conocer el directorio actual del proceso y, puede ser, el disco NFS montado que tiene problemas, puede usar un comando similar al siguiente ejemplo (reemplace 31134 con el número de proceso inactivo):

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

Descubrí que al dar el comando umount con el interruptor -f (forzar), al sistema de archivos nfs montado relacionado, se pudo reactivar el proceso de suspensión:

umount -f /auto/pippo

el sistema de archivos no se desmontó porque estaba ocupado, pero el proceso relacionado se despertó y pude resolver el problema sin reiniciar.

Valerio Di Giampietro
fuente
1

Suponiendo que su proceso es un solo subproceso y que está utilizando E / S de bloqueo, su proceso se bloqueará esperando que se complete la E / S. El kernel elegirá otro proceso para ejecutar mientras tanto en función de la bondad, la prioridad, el tiempo de última ejecución, etc. Si no hay otros procesos ejecutables, el kernel no ejecutará ninguno; en su lugar, le dirá al hardware que la máquina está inactiva (lo que resultará en un menor consumo de energía).

Los procesos que están esperando que se complete la E / S suelen aparecer en el estado D en, por ejemplo, psy top.

derobert
fuente
Lancé varios procesos usando aproximadamente el 10% de la memoria total. Noté que muchos de ellos están en estado D. ¿Se debe a una E / S lenta en esta máquina en particular? Digamos que tengo 9 procesos, pueden estar compitiendo por IO y muchos de ellos están en el estado D.
Kemin Zhou
@KeminZhou En comparación con las velocidades de la CPU, la E / S es bastante lenta, incluso la E / S rápida. Un solo proceso pesado de E / S puede ocupar fácilmente un disco magnético, incluso un SSD. 10 Los procesos pesados ​​de E / S pueden ocupar bastantes.
derobert
1

Sí, la tarea se bloquea en la llamada al sistema read (). Se ejecuta otra tarea que está lista, o si no hay otras tareas listas, se ejecuta la tarea inactiva (para esa CPU).

Una lectura de disco normal que bloquea hace que la tarea entre en el estado "D" (como han señalado otros). Estas tareas contribuyen al promedio de carga, aunque no consuman la CPU.

Algunos otros tipos de E / S, especialmente ttys y red, no se comportan exactamente igual: el proceso termina en el estado "S" y se puede interrumpir y no cuenta contra el promedio de carga.

MarkR
fuente
0

Sí, las tareas en espera de E / S se bloquean y se ejecutan otras tareas. La selección de la siguiente tarea la realiza el programador de Linux .

Martin contra Löwis
fuente
0

Generalmente el proceso se bloqueará. Si la operación de lectura está en un descriptor de archivo marcado como no bloqueante o si el proceso está usando E / S asíncrona, no se bloqueará. Además, si el proceso tiene otros subprocesos que no están bloqueados, pueden continuar ejecutándose.

La decisión de qué proceso se ejecutará a continuación depende del planificador del kernel.

Benno
fuente