flowchart TD
Proceso[Proceso] --> Recursos("Recursos Compartidos\nMemoria · Archivos · Espacio de direcciones")
subgraph Hilos [Hilos del Proceso]
Hilo1[Hilo 1]
Hilo2[Hilo 2]
Hilo3[Hilo 3]
Hilo1 ~~~ Hilo2 ~~~ Hilo3
end
Proceso --> Hilos
Hilo1 -->|Propio| Pila1("Pila + Registros + PC")
Hilo2 -->|Propio| Pila2("Pila + Registros + PC")
Hilo3 -->|Propio| Pila3("Pila + Registros + PC")
5 Los hilos (threads) y el TCB
5.1 ¿Qué es un hilo?
Un hilo (thread) es la unidad más pequeña de ejecución que el sistema operativo puede planificar en la CPU. Se trata de una secuencia de instrucciones que se ejecuta de forma independiente, pero dentro del contexto de un proceso.
La diferencia clave entre un proceso y un hilo radica en los recursos: un proceso posee su propio espacio de direcciones, archivos abiertos y memoria asignada. Los hilos que pertenecen a un mismo proceso comparten todos esos recursos, pero cada uno mantiene sus propios elementos de ejecución:
- Contador de programa: indica la siguiente instrucción a ejecutar.
- Pila de ejecución (stack): almacena variables locales y llamadas a funciones.
- Conjunto de registros: refleja el estado actual de la CPU para ese hilo.
Esta forma de organización convierte al hilo en un proceso ligero: crear un hilo es más rápido que crear un proceso completo, y el cambio de contexto entre hilos del mismo proceso tiene menor costo, ya que no es necesario cambiar el espacio de direcciones. Por ello, los hilos son ampliamente utilizados en aplicaciones modernas para lograr concurrencia y mejorar la capacidad de respuesta.
5.1.1 Ejemplo didáctico: hilos en una aplicación móvil
Consideremos una aplicación móvil que realiza varias tareas al mismo tiempo. Cada tarea se asigna a un hilo diferente:
flowchart TD
App[Aplicación Móvil] --> Hilo1[Hilo 1: Interfaz gráfica]
App --> Hilo2[Hilo 2: Descarga de imágenes]
App --> Hilo3[Hilo 3: Guardado automático]
subgraph Recursos Compartidos
Memoria[Memoria]
Archivos[Archivos abiertos]
end
Hilo1 -->|Acceso| Memoria
Hilo1 -->|Acceso| Archivos
Hilo2 -->|Acceso| Memoria
Hilo2 -->|Acceso| Archivos
Hilo3 -->|Acceso| Memoria
Hilo3 -->|Acceso| Archivos
- Hilo 1 (interfaz gráfica): mantiene la pantalla actualizada y responde a las interacciones del usuario (toques, gestos, navegación).
- Hilo 2 (descarga de imágenes): obtiene contenido desde internet en segundo plano, sin bloquear la interfaz.
- Hilo 3 (guardado automático): persiste el progreso del usuario de forma periódica.
La ventaja de esta separación es directa: si la descarga de imágenes se demora o falla, la interfaz sigue respondiendo con normalidad y el progreso se guarda sin interrupciones. Sin hilos, la aplicación tendría que esperar a que cada tarea termine antes de atender la siguiente, lo que produciría una experiencia lenta y poco fluida.
5.2 Thread Control Block (TCB)
Así como el sistema operativo utiliza un PCB (Process Control Block) para gestionar cada proceso, utiliza un TCB (Thread Control Block) para gestionar cada hilo. El TCB es la estructura de datos que almacena toda la información necesaria para que el sistema operativo pueda planificar, pausar, reanudar o finalizar un hilo de forma individual.
flowchart TB
TCB["Thread Control Block (TCB)"]
TCB --> TID["TID<br>Identificador único del hilo"]
TCB --> PC["Contador de programa<br>Siguiente instrucción a ejecutar"]
TCB --> Registros["Registros de CPU<br>Estado actual de los registros"]
TCB --> SP["Puntero de pila<br>Dirección del tope de la pila"]
TCB --> Estado["Estado del hilo<br>Listo · En ejecución · Bloqueado"]
TCB --> Prioridad["Prioridad<br>Nivel de preferencia para el planificador"]
TCB --> PCB["Enlace al PCB<br>Referencia al proceso padre"]
Cada campo cumple un rol específico:
- TID (Thread ID): identifica de manera única al hilo dentro del sistema.
- Contador de programa: indica exactamente en qué punto del código se encuentra el hilo.
- Registros de CPU: se guardan y restauran durante cada cambio de contexto para que el hilo retome su ejecución sin perder su estado.
- Puntero de pila: señala la posición actual en la pila del hilo, necesaria para gestionar llamadas a funciones y variables locales.
- Estado del hilo: puede ser listo (esperando turno en la CPU), en ejecución o bloqueado (esperando un recurso o evento).
- Prioridad: determina qué tan pronto el planificador le asignará tiempo de CPU frente a otros hilos.
- Enlace al PCB: vincula al hilo con su proceso padre, permitiendo acceder a los recursos compartidos (memoria, archivos abiertos, etc.).
Gracias al TCB, el sistema operativo puede realizar cambios de contexto entre hilos de forma eficiente: guarda el estado del hilo saliente en su TCB y carga el estado del hilo entrante desde el suyo.
5.3 Comunicación entre Procesos (IPC)
La Comunicación entre Procesos o IPC (Inter-Process Communication) es el conjunto de mecanismos que el sistema operativo ofrece para que los procesos puedan intercambiar datos y coordinar sus acciones. Sin IPC, cada proceso sería una entidad aislada, incapaz de colaborar con los demás.
En sistemas Unix/Linux, los principales mecanismos de IPC son:
Señales: notificaciones asíncronas que un proceso envía a otro para indicar que ocurrió un evento. Por ejemplo, al presionar
Ctrl+Cen la terminal, el sistema envía la señalSIGINTal proceso en primer plano para solicitar su terminación.Pipes (tuberías): canales unidireccionales que conectan la salida estándar de un proceso con la entrada estándar de otro. En la terminal se representan con el símbolo
|. Por ejemplo,ls | grep ".txt"envía la lista de archivos al procesogrep, que filtra solo los que terminan en.txt.Semáforos: mecanismos de sincronización que controlan el acceso a recursos compartidos. Funcionan como un contador: antes de acceder al recurso, el proceso “baja” el semáforo; si el valor llega a cero, los demás procesos deben esperar. Esto evita las condiciones de carrera, es decir, situaciones donde el resultado depende del orden impredecible en que los procesos acceden a un mismo recurso.
Colas de mensajes: permiten que los procesos envíen y reciban mensajes estructurados a través de una cola gestionada por el sistema operativo. Los mensajes se conservan en orden (FIFO) hasta que el proceso receptor los extrae.
Memoria compartida: permite que múltiples procesos accedan a una misma región de memoria RAM. Es el mecanismo de IPC más rápido, ya que no requiere copiar datos entre procesos. Sin embargo, exige mecanismos de sincronización adicionales (como semáforos o mutexes) para evitar lecturas y escrituras simultáneas que corrompan los datos.
La elección del mecanismo depende del caso de uso: las señales son ideales para notificaciones simples, los pipes para encadenar procesos secuenciales, y la memoria compartida para transferencias de datos de alto volumen donde el rendimiento es crítico.