2009-09-25 10 views
74

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

Respuesta

70

Mientras espera read() o write() a/desde un retorno de 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 encuentre en ese estado. Un proceso que espera un retorno de ioctl() también se pondrá a dormir de esta manera.

Una excepción a esto es cuando se abre un archivo (como un dispositivo de caracteres terminal u otro) en O_NONBLOCK modo, pasó cuando su supone que un dispositivo (como un módem) necesitará tiempo para inicializar. Sin embargo, indicó dispositivos de bloque en su pregunta. Además, nunca he probado un ioctl() que es probable que bloquee en un disco abierto en modo no bloqueo (al menos no a sabiendas).

La elección de otro proceso depende totalmente del planificador que esté utilizando, así como de lo que otros procesos hayan podido hacer para modificar sus ponderaciones dentro de ese planificador.

Algunos programas de espacio de usuario bajo ciertas circunstancias han permanecido en este estado para siempre, hasta que se reinician. Estos se agrupan típicamente con otros "zombies", pero el término no sería correcto ya que técnicamente no están extintos.

+1

"Un proceso que espera un retorno de ioctl() también se pondrá a dormir de esta manera". Acabo de matar mi proceso de espacio de usuario esperando en un IOCTL de bloqueo por lo que esto no es cierto. A menos que no entienda mal – Hamzahfrq

+0

Sería tremendamente difícil medir el tiempo de tal prueba. Los procesos ininterrumpibles no se pueden matar; si fue capaz de matarlo, entonces simplemente estaba bloqueando (el kernel no estaba en el medio de ninguna parte del ioctl, y copió cualquier respuesta correspondiente al espacio del usuario en la ubicación que aprobó (o al menos no estaba en el medio de copiar)). Linux también ha cambiado _mucho_ desde 2009 cuando esto fue escrito; el fenómeno es mucho menos observable que antes. –

1

Suponiendo que su proceso es de un solo hilo y que está utilizando E/S de bloqueo, su proceso bloqueará la espera de que se complete la E/S. Mientras tanto, el kernel escogerá otro proceso para ejecutar basado en la bondad, la prioridad, el último tiempo de ejecución, etc. Si no hay otros procesos ejecutables, el kernel no ejecutará ninguno; en su lugar, indicará al hardware que la máquina está inactiva (lo que dará como resultado un menor consumo de energía).

Los procesos que están esperando a que se complete la E/S normalmente aparecen en el estado D en, por ejemplo, ps y top.

+0

Lancé varios procesos usando aproximadamente el 10% de la memoria total. Noté que muchos de ellos están en estado D. ¿Esto se debe a una IO 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. –

+0

@KeminZhou En comparación con las velocidades de la CPU, la E/S es bastante lenta, incluso la E/S rápida. Un único proceso pesado de E/S puede ocupar fácilmente un disco magnético, incluso un disco SSD. 10 procesos pesados ​​de E/S podrían ocupar bastantes. – derobert

0

Sí, las tareas que esperan IO están bloqueadas y se ejecutan otras tareas. La selección de la siguiente tarea se realiza por el Linux scheduler.

0

En general, 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á utilizando IO asíncrono, no se bloqueará. Además, si el proceso tiene otros hilos que no están bloqueados, pueden continuar ejecutándose.

La decisión sobre qué proceso se ejecuta a continuación corresponde al scheduler en el kernel.

6

Un proceso que realiza E/S se pondrá en D estado (suspensión ininterrumpible), que libera la CPU hasta que hay una interrupción de hardware que le dice a la CPU que vuelva a ejecutar el programa. Ver man ps para los otros estados del proceso.

Dependiendo de su núcleo, no es un programador proceso, que realiza un seguimiento de una cola de ejecución de procesos listos para ejecutar. Esto, junto con un algoritmo de programación, le dice al núcleo qué proceso asignar a qué CPU. Hay procesos kernel y procesos de usuario a considerar. A cada proceso se le asigna un segmento de tiempo, que es un fragmento de tiempo de CPU que puede usar. Una vez que el proceso utiliza todo su segmento de tiempo, se marca como caducado y se le da menor prioridad en el algoritmo de programación.

En el 2.6 kernel, hay un O (1) programador de complejidad de tiempo, así 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 preemption y el balanceo 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.

1

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

Una lectura normal del disco de bloqueo hace que la tarea entre en el estado "D" (como otros han notado). Estas tareas contribuyen al promedio de carga, a pesar de que no consumen la CPU.

Algunos otros tipos de IO, especialmente ttys y red, no se comportan de la misma manera: el proceso termina en estado "S" y puede interrumpirse y no cuenta en el promedio de carga.

112

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

Desde el punto de vista del programador (también se dice "en el espacio de usuario"), esto se llama llamada del sistema de bloqueo. Si llama al write(2) (que es un envoltorio de libc delgado alrededor de la llamada del sistema del mismo nombre), su proceso no se detiene exactamente en ese límite: continúa, en el lado del 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 un comando para recuperar un bloque en el disco se envía al hardware adecuado: esta es una muy operación rápida la mayor parte del tiempo.

ENTONCES el proceso se pone en estado de reposo (en el espacio del kernel, el bloqueo se denomina dormir - nada está siempre 'bloqueado' desde el punto de vista del kernel). Se despertará nuevamente una vez que el hardware finalmente haya obtenido los datos correctos, luego el proceso se marcará como ejecutable, programado y ejecutado tan pronto como el planificador lo permita.

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

Es posible invocar la mayoría del sistema de E/S llamadas en no-bloqueo (ver O_NONBLOCK en open(2) y fcntl(2)). En este caso, el sistema llama de inmediato y solo informa sobre el envío correcto de la operación del disco. El programador deberá verificar explícitamente en un momento posterior si la operación se completó, con éxito o no, y recuperar 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 (cuyo nombre exacto es TASK_UNINTERRUPTIBLE de nombres de estado de Linux) son incorrectas. El estado D es un modo de suspensión especial que solo se desencadena en una ruta de código de espacio de kernel, cuando esa ruta de código no se puede interrumpir (porque sería complejo programar), la mayoría de las veces con la esperanza que bloqueará muy pronto. Creo que la mayoría de los "estados D" son realmente invisibles, tienen una vida muy corta y no se pueden observar con herramientas de muestreo como 'top'.

Pero a veces encontrará esos procesos imposibles de resolver en 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ódigos VFS que suponen que siempre llegan a los discos locales y detección rápida de errores (en SATA, un tiempo de espera de error sería de unos 100 ms), y NFS que realmente obtiene datos de la red que es más resistente y tiene una recuperación lenta (es común un tiempo de espera TCP de 300 segundos). Lea this article para la solución genial presentada en Linux 2.6.25 con el estado TASK_KILLABLE. Antes de esta era, había un truco en el que podías enviar señales a los clientes del proceso NFS enviando un SIGKILL al hilo del kernel rpciod, pero olvídate de ese feo truco & hellip;

+2

+1 para la respuesta detallada, pero tenga en cuenta que este hilo ha tenido una respuesta aceptada durante casi dos años. Pulse el enlace "Preguntas" si desea echar un vistazo a las preguntas más recientes. Bienvenido a Stack Overflow, ¡y gracias por contribuir! – GargantuChet

+17

Esta respuesta es la única que menciona NFS, que en algunos entornos es la explicación más común para procesos en el estado D. +1. – Pinko

+12

Muy buena respuesta, gracias. También tenga en cuenta que el proceso entra en el estado D mientras espera las páginas que se han intercambiado, por lo que un proceso de agitación estará en el estado D durante un tiempo prolongado. – cha0site

2

Como ya han explicado otros, los procesos en el estado "D" (suspensión ininterrumpida) son responsables del proceso de bloqueo de ps. Para mí, esto ha sucedido muchas veces con RedHat 6.x y directorios home de NFS automáticos.

lista Para procesos en el estado D se pueden utilizar 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 montado en NFS que tiene problemas puede utilizar un comando similar al ejemplo siguiente (reemplace 31134 con el número de proceso para dormir):

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

me encontré con que dar la orden umount con el -f (fuerza) de conmutación, a la relación montado sistema de archivos NFS, fue capaz de Wake el proceso de dormir:

umount -f /auto/pippo 

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