Los estados de un proceso - Procesos e Hilos
← Procesos e Hilos Bloque 2 · Estados y cambio de contexto · Tema 6 de 43

Tema 6

Los estados de un proceso

Un proceso no está siempre haciendo lo mismo. A lo largo de su vida pasa por situaciones distintas: recién creado y esperando ser admitido, listo para ejecutarse pero esperando turno, ejecutándose en la CPU, bloqueado esperando un evento, y finalmente terminado. Esos son los estados de un proceso, y las transiciones entre ellos son el mecanismo por el que el sistema operativo organiza el trabajo. En este tema verás los cinco estados clásicos, el diagrama que los relaciona, las transiciones y los casos especiales, como la suspensión y el proceso zombi.

1. Qué es un estado

El estado de un proceso es la situación en la que se encuentra en un instante dado, desde el punto de vista del planificador: si está esperando ser admitido, si está listo para ejecutarse, si está usando la CPU, si está esperando un evento o si ya terminó. El estado determina en que cola del sistema está el proceso y que puede hacer el núcleo con él.

El estado es uno de los campos del PCB, como viste en el tema 4. Cambia a lo largo de la vida del proceso, y cada cambio es una transición que el núcleo registra en el PCB. Por eso, cuando preguntas «¿en que estado está este proceso?», el núcleo no necesita adivinar: solo lee el campo state del task_struct.

El estado no es lo mismo que la actividad del programa. Un proceso puede estar «listo» sin estar haciendo nada útil, o «bloqueado» esperando el disco mientras su código está perfectamente válido. El estado describe la relación del proceso con el sistema operativo, no lo que hace el programa.

El estado es la posición en la cola

Piensa en el estado como la posición de un cliente en un sistema de atención: esperando en la puerta (nuevo), en la fila de espera (listo), siendo atendido (en ejecución), esperando que llegue un documento (bloqueado) o ya atendido y retirado (terminado). El estado dice en que cola está, no que está pensando el cliente.

2. Los cinco estados clásicos

El modelo clásico de estados de un proceso, el que aparece en los libros de texto y en la mayoría de los sistemas operativos, tiene cinco estados:

EstadoNombre en inglésQue significa
NuevoNewEl proceso acaba de crearse. El núcleo está preparando su PCB, su espacio de direcciones y sus recursos, pero aún no lo ha admitido en el sistema. No puede ejecutarse.
ListoReadyEl proceso está preparado para ejecutarse: tiene todo lo que necesita (memoria, recursos) y solo espera que el planificador le asigne la CPU. Está en la cola de listos.
En ejecuciónRunningEl proceso está usando la CPU en este momento. En un sistema con un solo núcleo, solo un proceso puede estar en este estado a la vez.
BloqueadoWaiting / BlockedEl proceso no puede ejecutarse porque está esperando que ocurra algo: que termine una operación de E/S, que llegue un dato de la red, que se libere un recurso, que expire un temporizador. Está en una cola de espera.
TerminadoTerminated / ExitEl proceso terminó su ejecución (con exit o por una señal). El núcleo libera sus recursos, pero el PCB puede quedar un tiempo como zombi hasta que el padre lo recoge.

Estos cinco estados son suficientes para describir la vida de un proceso en la mayoría de los casos. Pero hay matices, como la suspensión, que veremos más adelante.

3. El diagrama de estados

Los cinco estados se conectan por transiciones que el núcleo dispara en respuesta a eventos. El diagrama clásico es este:

Diagrama de los cinco estados de un proceso. Nuevo apunta a listo por admit. Listo y en ejecución se alternan por dispatch y timeout o evento. En ejecución puede ir a bloqueado por event wait, y bloqueado vuelve a listo por event occurs. En ejecución va a terminado por release. Nuevo Listo En ejecución Bloqueado Terminado admit dispatch timeout / interrupción event wait event occurs release
El diagrama de los cinco estados. Las transiciones se disparan por eventos: admisión, asignación de CPU, expiración del cuanto, espera de evento, ocurrencia del evento y terminación.

Las transiciones son las flechas del diagrama. Cada una corresponde a un evento concreto que el núcleo detecta y procesa. Veámoslas una por una.

4. Las transiciones en detalle

admit (Nuevo → Listo)

Cuando un proceso se crea (con fork o equivalente), el núcleo lo pone en estado «nuevo» mientras prepara su PCB y su espacio de direcciones. Una vez que todo está listo, lo admite al sistema: lo mueve a «listo» y lo pone en la cola de listos. En la práctica, esta transición es muy rápida y casi inmediata.

dispatch (Listo → En ejecución)

El planificador elige un proceso de la cola de listos y le asigna la CPU. El núcleo hace un cambio de contexto: guarda el estado del proceso que se estaba ejecutando (si lo había) y carga el del elegido. A partir de ese momento, el proceso está «en ejecución».

timeout (En ejecución → Listo)

En los sistemas con tiempo compartido, un proceso no puede usar la CPU indefinidamente. El núcleo le asigna un cuanto de tiempo (típicamente unos milisegundos). Cuando el cuanto expira, el núcleo interrumpe al proceso, lo mueve de «en ejecución» a «listo» y lo pone de nuevo en la cola de listos. Es una transición involuntaria: el proceso no la pide.

event wait (En ejecución → Bloqueado)

Cuando un proceso en ejecución necesita esperar algo (leer del disco, recibir datos de la red, esperar a un hijo, adquirir un recurso), llama a una operación que lo bloquea. El núcleo lo mueve a «bloqueado» y lo pone en la cola de espera correspondiente. El proceso deja la CPU, que se asigna a otro.

event occurs (Bloqueado → Listo)

Cuando el evento que el proceso esperaba ocurre (los datos llegaron, el disco terminó, el hijo terminó), el núcleo lo despierta: lo mueve de «bloqueado» a «listo» y lo pone en la cola de listos. El proceso aún no se ejecuta: solo está listo para cuando le toque el turno.

release (En ejecución → Terminado)

Cuando un proceso termina (con exit, return en main, o por una señal fatal), el núcleo lo mueve a «terminado». Libera sus recursos (memoria, archivos, descriptores) y notifica al padre. El PCB queda como zombi hasta que el padre lo recoge.

Las transiciones son eventos del núcleo

Ninguna de estas transiciones la decide el programa. El programa solo hace cosas (llamar a read, terminar, etc.); el núcleo detecta esas acciones y cambia el estado en consecuencia. Por eso el estado es una propiedad del sistema operativo, no del programa.

5. Suspensión y swap

Los cinco estados anteriores asumen que el proceso está en memoria principal. Pero un sistema puede tener más procesos que memoria, y entonces el núcleo necesita suspender algunos: sacarlos de la memoria principal y guardarlos en disco (swap) para liberar espacio. Un proceso suspendido no puede ejecutarse, ni siquiera si está listo, porque no está en memoria.

La suspensión introduce dos estados nuevos:

EstadoQue significa
Suspendido y listoEl proceso estaba listo para ejecutarse, pero se sacó de la memoria. Cuando se vuelva a cargar, estará listo de nuevo.
Suspendido y bloqueadoEl proceso estaba bloqueado esperando un evento, y además se sacó de la memoria. Cuando se vuelva a cargar, seguirá bloqueado esperando el mismo evento.

La suspensión la decide el núcleo (o el usuario, con señales como SIGSTOP), no el proceso. Es una herramienta para gestionar la memoria: cuando hay poca RAM, el núcleo suspende procesos que no se están usando activamente y los reanuda cuando hay espacio. Es el tema del curso de gestión de memoria.

En la práctica, en sistemas modernos con mucha RAM, la suspensión por swap es menos frecuente, pero el mecanismo sigue existiendo y se usa en contenedores, máquinas virtuales y sistemas embebidos.

6. El modelo de siete estados

Combinando los cinco estados clásicos con los dos suspendidos, se obtiene el modelo de siete estados, que es el que usan los sistemas operativos reales:

Modelo de siete estados. Los cinco clásicos más dos suspendidos. Nuevo a listo por admit. Listo y en ejecución se alternan. En ejecución puede ir a bloqueado, Terminado. Bloqueado puede ir a listo o a suspendido y bloqueado. Listo puede ir a suspendido y listo. Los suspendidos vuelven por activate. Nuevo Listo En ejecución Terminado Bloqueado Susp. y bloqueado Susp. y listo Flechas sólidas: transiciones normales. Flechas discontinuas: suspensión y reactivación. Un proceso suspendido y bloqueado puede pasar a suspendido y listo cuando ocurre el evento que esperaba.
El modelo de siete estados. Los dos estados suspendidos (discontinuos) se añaden para gestionar la falta de memoria principal.

Las transiciones nuevas son:

7. El proceso zombi

Cuando un proceso termina, no desaparece inmediatamente. El núcleo lo mueve a «terminado», libera su memoria, sus archivos y sus descriptores, pero conserva su PCB con el código de salida. Ese proceso se llama zombi: ya no se ejecuta ni ocupa recursos, pero sigue existiendo en la tabla de procesos hasta que su padre lo «recoge» con wait().

El zombi es un estado intermedio entre «terminado» y «liberado». Sirve para que el padre pueda consultar el código de salida del hijo. Si el padre nunca llama a wait(), el zombi se queda ahí indefinidamente, ocupando una entrada en la tabla de procesos. Si hay muchos zombis, se agota el límite de procesos y el sistema no puede crear procesos nuevos.

En ps, un zombi se reconoce por la letra Z en la columna STAT y por el nombre del proceso entre corchetes. En /proc/PID/status, el estado es Z (zombie).

terminal · ver un proceso zombi
$ ps -o pid,ppid,stat,comm -p 503
    PID    PPID STAT COMMAND
    503     502 Z    [worker]
$ grep state /proc/503/status
State:	Z (zombie)

Si el padre termina antes que el hijo (o antes de recogerlo), el hijo queda huérfano y el núcleo le reasigna como padre al proceso 1 (o a un subreaper). El proceso 1, por diseño, recoge automáticamente a todos los huérfanos que terminan, así que un zombi huérfano no dura mucho. Es el tema 26.

Los zombis no consumen CPU ni memoria

Un zombi no ejecuta código ni ocupa memoria (más allá del PCB mínimo). Pero sí ocupa una entrada en la tabla de procesos, y si se acumulan, pueden agotar el límite de procesos del sistema. La solución es siempre recoger a los hijos con wait() o waitpid().

8. Los estados en linux (adelanto)

Linux no usa exactamente los cinco estados clásicos. En su lugar, usa un conjunto de estados que se muestra en la columna STAT de ps y en /proc/PID/status. El tema 7 los detalla con programas que provocan cada uno, pero aquí va un adelanto:

LetraEstado en linuxCorresponde a
RRunningEn ejecución o listo para ejecutarse (Linux no distingue entre ambos en la salida de ps).
SSleeping (interruptible)Bloqueado esperando un evento, y puede despertarse por una señal.
DUninterruptible sleepBloqueado en una operación de E/S de disco, no puede despertarse por señales.
TStoppedDetenido por una señal (SIGSTOP, SIGTSTP) o por el depurador.
ZZombieTerminado, pero no recogido por el padre.
tTracing stopDetenido por el depurador (ptrace).
XDeadEl proceso está siendo destruido (estado transitorio, casi nunca se ve).

La letra puede ir seguida de modificadores: + (en primer plano), s (líder de sesión), l (multihilo), < (alta prioridad), N (baja prioridad). Por ejemplo, Ss+ significa: dormido, líder de sesión, en primer plano.

9. Cómo el núcleo gestiona los estados

El núcleo gestiona los estados a través del planificador y de las colas. Cada estado corresponde a una cola o a una situación especial:

EstadoCola donde estáQuién lo saca de ahí
NuevoNinguna (se está creando)El núcleo, al terminar de crearlo.
ListoCola de listosEl planificador, al asignarle la CPU.
En ejecuciónNinguna (está en la CPU)El núcleo, por timeout, bloqueo o terminación.
BloqueadoCola de espera del eventoEl núcleo, cuando ocurre el evento.
Terminado / ZombiNinguna (espera al padre)El padre, al llamar a wait().

El planificador es el componente del núcleo que decide que proceso de la cola de listos pasa a «en ejecución». Es el tema del curso siguiente (planificación de la CPU). Aquí nos basta con saber que existe y que es quien dispara la transición dispatch.

Cuando un proceso se bloquea, el núcleo no solo cambia su estado: también lo saca de la cola de listos y lo pone en la cola de espera correspondiente. Así, el planificador no lo considera candidato a ejecutarse hasta que se desbloquee. Cuando el evento ocurre, el núcleo lo saca de la cola de espera y lo pone en la cola de listos.

10. Un programa que provoca estados

El siguiente programa hace distintas cosas para provocar varios estados, y te permite observarlos con ps desde otra terminal:

estados.c
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

volatile sig_atomic_t continuar = 1;

void manejador(int sig)
{
    continuar = 0;
}

int main(void)
{
    printf("PID: %d\n", (int) getpid());
    printf("Observa este proceso con: ps -o pid,stat,wchan,comm -p %d\n",
           (int) getpid());

    /* 1. Estado R: usar la CPU sin parar */
    printf("\n[1] Usando la CPU durante 5 segundos (estado R)...\n");
    unsigned long x = 0;
    for (int i = 0; i < 5; i++) {
        for (volatile int j = 0; j < 100000000; j++) x++;
        sleep(1);
    }

    /* 2. Estado S: dormir (bloqueado interruptible) */
    printf("\n[2] Durmiendo 10 segundos (estado S)...\n");
    sleep(10);

    /* 3. Estado T: detenerse por SIGSTOP */
    printf("\n[3] Deteniéndose con SIGSTOP. Envía SIGCONT para continuar.\n");
    fflush(stdout);
    raise(SIGSTOP);

    /* 4. Estado D: no se puede provocar fácilmente desde un programa */
    printf("\n[4] Continuando tras SIGCONT.\n");

    /* 5. Terminar */
    printf("\n[5] Terminando (estado Z hasta que el padre recoge).\n");
    return 0;
}

Al ejecutarlo, puedes observar desde otra terminal como cambia el estado:

terminal · observar los estados
$ gcc -std=c17 -Wall -Wextra -o estados estados.c
$ ./estados &
[1] 710
PID: 710
[1] Usando la CPU durante 5 segundos (estado R)...
$ ps -o pid,stat,wchan,comm -p 710
    PID STAT WCHAN  COMMAND
    710 R+   -      estados
$ sleep 6; ps -o pid,stat,wchan,comm -p 710
    PID STAT WCHAN  COMMAND
    710 S+   hrtimer_nanosleep estados
$ sleep 12; ps -o pid,stat,wchan,comm -p 710
    PID STAT WCHAN  COMMAND
    710 T+   -      estados
$ kill -CONT 710

La columna WCHAN muestra en que función del núcleo está dormido el proceso. Cuando está en R, no está dormido (aparece -). Cuando está en S por sleep, aparece hrtimer_nanosleep. Es una pista útil para saber por que un proceso está bloqueado.

11. Resumen

12. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Cuáles son los cinco estados clásicos de un proceso?

Nuevo, listo, en ejecución, bloqueado y terminado. Son los estados que describen la vida de un proceso desde que se crea hasta que se libera.

2. ¿Que transición lleva a un proceso de «listo» a «en ejecución»?

La transición dispatch, que dispara el planificador al elegir un proceso de la cola de listos y asignarle la CPU.

3. ¿Que diferencia hay entre «listo» y «en ejecución»?

«Listo» significa que el proceso puede ejecutarse pero está esperando turno en la cola de listos. «En ejecución» significa que está usando la CPU en este momento. En un sistema con un solo núcleo, solo un proceso puede estar en ejecución a la vez.

4. ¿Que es un proceso zombi?

Es un proceso que terminó su ejecución pero cuyo PCB se conserva (con el código de salida) hasta que su padre lo recoge con wait(). No consume CPU ni memoria, pero ocupa una entrada en la tabla de procesos.

5. ¿Que es la suspensión y para que sirve?

Es sacar un proceso de la memoria principal y guardarlo en disco (swap) para liberar espacio. Introduce los estados «suspendido y listo» y «suspendido y bloqueado». La decide el núcleo, no el proceso.

6. ¿Que letra muestra ps para un proceso bloqueado en una operación de disco?

La letra D (uninterruptible sleep). Es un estado bloqueado en E/S de disco que no puede interrumpirse por señales, a diferencia de S (sleeping interruptible).

7. ¿Que significa la transición timeout?

Es cuando expira el cuanto de tiempo asignado a un proceso en ejecución. El núcleo lo interrumpe, lo mueve de «en ejecución» a «listo» y lo pone de nuevo en la cola de listos. Es involuntaria.

8. ¿Por que linux no distingue entre «listo» y «en ejecución» en ps?

Porque ambos estados se representan con la letra R (running). La distinción existe internamente en el núcleo, pero para el usuario no es relevante: un proceso en R está activo, ya sea ejecutándose o esperando turno inmediato.

9. ¿Que es la columna WCHAN en ps?

Muestra en que función del núcleo está dormido el proceso (si está bloqueado). Si el proceso está en R, aparece -. Es útil para saber por que un proceso está bloqueado.

10. ¿Que ocurre si un proceso termina y su padre no llama a wait?

El proceso queda como zombi indefinidamente, ocupando una entrada en la tabla de procesos. Si se acumulan muchos zombis, se puede agotar el límite de procesos del sistema.

Para practicar

  1. Compila y ejecuta estados.c, y desde otra terminal observa como cambia el estado con ps -o pid,stat,wchan,comm.
  2. Crea un proceso zombi: escribe un programa que haga fork(), que el hijo termine inmediatamente y que el padre no llame a wait(). Observa el zombi con ps y /proc/PID/status.
  3. Lanza un proceso en segundo plano y deténlo con kill -STOP PID. Observa el estado T. Reanúdalo con kill -CONT PID.
  4. Observa los estados de los procesos de tu sistema con ps -e -o stat,comm | sort | uniq -c para contar cuántos hay en cada estado.
  5. Ejecuta un comando que haga E/S de disco intensiva (como dd) y observa si aparece en estado D.
  6. Compara la salida de ps -e -o stat con los estados del modelo de siete estados y anota que letras corresponden a cada uno.