Procesos e hilos — ejercicios tipo examen con estados que trazar, fork() que contar e hilos que lo comparten casi todo (y el «Hola» que salió ocho veces)
Mi for con tres fork() imprimió ocho «Hola» en lugar de cuatro, y la lección me sirvió más para el examen que para la práctica: en el test de IC2 hay preguntas de contar procesos, de qué estado viene después de cuál y de qué tiene propio un hilo, y en todas la trampa es la misma que la mía. Se responden bien si tienes el dibujo correcto en la cabeza, no si recuerdas frases sueltas.
Este artículo es la parte práctica de la teoría de procesos e hilos: un test interactivo con todos los formatos del examen (única, múltiple que penaliza, verdadero o falso, huecos, relacionar, ordenar, respuesta corta y dos tablas de cálculo), cuatro preguntas de desarrollo con su respuesta modelo, el tema entero en un dibujo y el chuletario para el último repaso. Las preguntas son originales: cubren los mismos conceptos que el examen, con otros datos y otra redacción.
Tabla de Contenidos
Cómo usar este artículo
- Haz el test sin mirar la teoría. Cada pregunta tiene su botón «Comprobar»: contesta, compruébala y lee la explicación, también cuando aciertes.
- En las múltiples, cuidado: penalizan como en el examen. Cada opción incorrecta marcada resta, así que marca solo lo que tengas claro.
- En las dos tablas, coge papel. En la de estados, dibuja los cinco estados y mueve a A y a B evento a evento; en la de
fork(), dibuja el árbol. Escribe los estados con la palabra exacta (nuevo, preparado, ejecución, bloqueado o terminado; las tildes y mayúsculas dan igual). - Apunta lo que falles y repásalo con el chuletario del final. Si fallas más de tres seguidas del mismo bloque, vuelve a esa sección de la teoría.
Test: procesos, estados, API e hilos
Son 31 preguntas en el orden del tema: qué es un proceso y su PCB (1-5), estados (6-11), colas, planificadores y cambio de contexto (12-17), la API de procesos (18-26) e hilos (27-31).
¿Cuál es la definición de proceso que esperan en el examen?
- Un programa en ejecución, con los recursos que el SO le asigna
- Un fichero ejecutable guardado en el disco
- Una rutina de servicio de interrupción
- Un hilo del núcleo que no tiene memoria propia
Solución
Respuesta: Un programa en ejecución, con los recursos que el SO le asigna
Un proceso es un programa en ejecución: el código más todo lo que hace falta para ejecutarlo (memoria, registros, PC, archivos abiertos y tiempo de CPU). El mismo programa puede dar lugar a varios procesos a la vez.
Marca si cada afirmación sobre los procesos es verdadera o falsa.
- Para ejecutarse, un proceso necesita memoria principal, tiempo de CPU y dispositivos de E/S.
- Un proceso nuevo se crea mediante una rutina de servicio de interrupción.
- Dos procesos pueden estar ejecutando el mismo programa al mismo tiempo.
- Un programa guardado en el disco es una entidad activa.
- Los procesos compiten por el tiempo de CPU y por las zonas de memoria.
Solución
- V — Para ejecutarse, un proceso necesita memoria principal, tiempo de CPU y dispositivos de E/S.
- F — Un proceso nuevo se crea mediante una rutina de servicio de interrupción.
- V — Dos procesos pueden estar ejecutando el mismo programa al mismo tiempo.
- F — Un programa guardado en el disco es una entidad activa.
- V — Los procesos compiten por el tiempo de CPU y por las zonas de memoria.
Necesita memoria principal (la RAM), no secundaria: el disco guarda el programa, pero para ejecutarlo hay que cargarlo en RAM.
Un proceso se crea con una llamada al sistema (fork o CreateProcess), no con una rutina de interrupción. Y abrir dos terminales con bash da dos procesos del mismo programa.
Relaciona cada zona de la memoria de un proceso con lo que guarda.
| text | |
| data | |
| heap | |
| stack |
Definiciones:
- El código máquina del programa
- Las variables globales y estáticas
- La memoria que se pide con malloc
- Variables locales, parámetros y direcciones de retorno
- Los registros de la CPU de cada hilo
Solución
- text → El código máquina del programa
- data → Las variables globales y estáticas
- heap → La memoria que se pide con malloc
- stack → Variables locales, parámetros y direcciones de retorno
De abajo arriba: text (código), data (globales), heap (memoria dinámica, crece hacia arriba) y stack (pila, crece hacia abajo). Los registros no están en ninguna zona de memoria: viven en la CPU y, cuando el proceso sale, en su PCB.
¿Qué zonas de la memoria de un proceso se copian desde el fichero ejecutable al cargarlo?
- text y data
- heap y stack
- Solo stack
- Las cuatro
Solución
Respuesta: text y data
text y data salen del ejecutable; heap y stack se crean y crecen mientras el proceso se ejecuta.
¿Qué información guarda el PCB (bloque de control de proceso)? Marca todas las correctas.
- El estado del proceso
- El contador de programa
- Una copia de los registros de la CPU
- Los archivos abiertos y el estado de E/S
- El código máquina del programa
- La tabla de vectores de interrupción
- Las variables locales de sus funciones
Solución
Respuesta: El estado del proceso · El contador de programa · Una copia de los registros de la CPU · Los archivos abiertos y el estado de E/S
El PCB guarda: estado, PC, registros, información de planificación (prioridad, tiempo esperando), de memoria, de E/S y archivos, y contable (tiempo de CPU consumido, PID). Ojo: es múltiple con penalización, así que marcar el código o las locales resta.
Relaciona cada estado con su descripción.
| Nuevo | |
| Preparado | |
| En ejecución | |
| Bloqueado | |
| Terminado |
Definiciones:
- No ejecutará más y el SO le retira los recursos
- El SO acaba de crearlo y aún no lo ha admitido
- Está en la CPU ejecutando instrucciones
- Lo tiene todo y solo espera a que le den la CPU
- Guardado en el disco con su PCB borrado
- Espera a que ocurra un evento, como el fin de una E/S
Solución
- Nuevo → El SO acaba de crearlo y aún no lo ha admitido
- Preparado → Lo tiene todo y solo espera a que le den la CPU
- En ejecución → Está en la CPU ejecutando instrucciones
- Bloqueado → Espera a que ocurra un evento, como el fin de una E/S
- Terminado → No ejecutará más y el SO le retira los recursos
La pareja que más se confunde es preparado frente a bloqueado: preparado espera a la CPU; bloqueado espera a otra cosa (el disco, la red, un hijo). Aunque le dieras la CPU a uno bloqueado, no podría avanzar.
gcc ha pedido al disco el contenido de un .c y todavía no ha llegado. ¿En qué estado está gcc?
- Bloqueado
- Preparado
- En ejecución
- Nuevo
Solución
Respuesta: Bloqueado
Pedir una E/S lleva de ejecución a bloqueado. Cuando el disco termine, una interrupción lo pasará a preparado.
El reproductor de música tiene sus datos en RAM y nada que esperar, pero la CPU la está usando otro proceso. ¿En qué estado está?
- Preparado
- Bloqueado
- En ejecución
- Terminado
Solución
Respuesta: Preparado
Preparado = esperando a que le asignen un procesador. Está en la cola de preparados, y el despachador lo elegirá cuando le toque.
Transiciones entre estados: marca si cada una existe en el diagrama de cinco estados.
- Un proceso bloqueado pasa directamente a ejecución cuando termina su E/S.
- Un proceso en ejecución vuelve a preparado cuando salta el temporizador.
- Un proceso preparado puede pasar a bloqueado sin haberse ejecutado.
- Un proceso nuevo pasa a preparado cuando el SO lo admite.
- Un proceso terminado puede volver a preparado si el usuario lo pide.
Solución
- F — Un proceso bloqueado pasa directamente a ejecución cuando termina su E/S.
- V — Un proceso en ejecución vuelve a preparado cuando salta el temporizador.
- F — Un proceso preparado puede pasar a bloqueado sin haberse ejecutado.
- V — Un proceso nuevo pasa a preparado cuando el SO lo admite.
- F — Un proceso terminado puede volver a preparado si el usuario lo pide.
Las seis flechas son: nuevo → preparado, preparado → ejecución, ejecución → preparado, ejecución → bloqueado, bloqueado → preparado y ejecución → terminado.
Para bloquearse hay que pedir algo (una E/S, un wait), y eso solo se puede hacer ejecutando instrucciones. Por eso a bloqueado solo se llega desde ejecución, y de bloqueado solo se sale a preparado: al terminar la E/S vuelve a la cola, no a la CPU.
Ordena la vida de un proceso gcc que se crea, lee un archivo del disco y termina (con una sola CPU ocupada por otros a ratos).
- La interrupción del disco lo devuelve a preparado
- bash hace fork(): el hijo nace en estado nuevo
- El despachador le da la CPU: pasa a ejecución
- El SO lo admite y lo pone en la cola de preparados
- Vuelve a la CPU y termina con exit(0)
- Pide el archivo al disco: pasa a bloqueado
Solución
Orden correcto:
- bash hace fork(): el hijo nace en estado nuevo
- El SO lo admite y lo pone en la cola de preparados
- El despachador le da la CPU: pasa a ejecución
- Pide el archivo al disco: pasa a bloqueado
- La interrupción del disco lo devuelve a preparado
- Vuelve a la CPU y termina con exit(0)
nuevo → preparado → ejecución → bloqueado → preparado → ejecución → terminado. Fíjate en el quinto paso: tras la E/S no vuelve a la CPU directamente, sino a la cola de preparados.
Dos procesos, A y B, comparten una CPU. Al empezar, A está en ejecución y B está preparado. Escribe el estado de cada uno después de cada evento (nuevo, preparado, ejecución, bloqueado o terminado).
| Paso | Evento | Estado de A | Estado de B |
|---|---|---|---|
| 1 | A pide un bloque al disco | ||
| 2 | El despachador elige a B | ||
| 3 | Llega la interrupción del disco de A | ||
| 4 | El temporizador expulsa a B | ||
| 5 | El despachador elige a A | ||
| 6 | A llama a exit(0) |
Solución
| Paso | Evento | Estado de A | Estado de B |
|---|---|---|---|
| 1 | A pide un bloque al disco | bloqueado | preparado |
| 2 | El despachador elige a B | bloqueado | ejecución |
| 3 | Llega la interrupción del disco de A | preparado | ejecución |
| 4 | El temporizador expulsa a B | preparado | preparado |
| 5 | El despachador elige a A | ejecución | preparado |
| 6 | A llama a exit(0) | terminado | preparado |
Paso 1: pedir E/S lleva de ejecución a bloqueado; B sigue preparado porque nadie lo ha elegido todavía (eso es el paso 2).
Paso 3: la interrupción solo despierta a A (a preparado); B sigue en la CPU. Paso 4: el temporizador saca a B a preparado, y en ese momento los dos están en la cola. En cada fila hay como mucho un proceso en ejecución: solo hay una CPU.
Completa el texto sobre las colas de procesos.
El SO organiza los ____ en colas de espera por el ____ o por los dispositivos de E/S. Las colas se implementan con ____ enlazadas, tablas o árboles, y el ____ inserta y extrae procesos de cada cola según su política.
Palabras:
- listas
- procesador
- pilas
- planificador
- registros
- PCB
- compilador
Solución
El SO organiza los PCB en colas de espera por el procesador o por los dispositivos de E/S. Las colas se implementan con listas enlazadas, tablas o árboles, y el planificador inserta y extrae procesos de cada cola según su política.
Lo que se mueve de cola en cola no es el proceso entero sino su PCB. Cada recurso (la CPU, cada disco) tiene su cola, y la política de planificación decide el orden.
Relaciona cada planificador con su función.
| Corto plazo (PCP) | |
| Largo plazo (PLP) | |
| Medio plazo (PMP) |
Definiciones:
- Reparte los bloques del disco entre los archivos
- Si la RAM está saturada, lleva al disco procesos bloqueados
- Decide qué trabajos entran en la cola de preparados
- Asigna y quita la CPU a los procesos preparados
Solución
- Corto plazo (PCP) → Asigna y quita la CPU a los procesos preparados
- Largo plazo (PLP) → Decide qué trabajos entran en la cola de preparados
- Medio plazo (PMP) → Si la RAM está saturada, lleva al disco procesos bloqueados
El PCP trabaja continuamente; el PLP, de vez en cuando (en sistemas por lotes o granjas de servidores) para conseguir una buena mezcla de trabajos; el PMP hace intercambio (swapping) cuando falta memoria.
¿Qué planificador se ejecuta con más frecuencia?
- El de corto plazo
- El de largo plazo
- El de medio plazo
- Los tres con la misma frecuencia
Solución
Respuesta: El de corto plazo
Corto, medio y largo hablan de cada cuánto actúan: el de corto plazo, constantemente.
¿Cómo se llama la técnica de llevar al disco procesos bloqueados para liberar memoria principal? (una palabra)
Solución
Respuesta: intercambio
Intercambio (swapping), y lo hace el planificador de medio plazo.
Sobre el cambio de contexto, marca verdadero o falso.
- Consiste en sacar un proceso de la CPU y reanudar otro.
- El estado del proceso que sale se guarda en su PCB.
- Se realiza en modo usuario para que sea más rápido.
- Mientras dura, ningún proceso de usuario avanza.
- El contexto del proceso desalojado se guarda en la memoria secundaria.
Solución
- V — Consiste en sacar un proceso de la CPU y reanudar otro.
- V — El estado del proceso que sale se guarda en su PCB.
- F — Se realiza en modo usuario para que sea más rápido.
- V — Mientras dura, ningún proceso de usuario avanza.
- F — El contexto del proceso desalojado se guarda en la memoria secundaria.
Es trabajo del SO, así que se hace en modo núcleo; el contexto va al PCB, que está en memoria principal. Es tiempo perdido, y por eso el hardware ofrece instrucciones para guardar y cargar registros de golpe (PUSHA/POPA en x86, LDM/STM en ARM).
¿Cómo se llama el módulo del SO que hace el cambio de contexto?
Solución
Respuesta: despachador
El despachador (dispatcher). No lo confundas con el planificador: el planificador decide quién va a la CPU; el despachador hace el cambio.
En Unix, ¿qué identifica a cada proceso de forma única?
- Su PID
- El nombre de su ejecutable
- La dirección de su pila
- El nombre del usuario que lo lanza
Solución
Respuesta: Su PID
Cada proceso tiene un PID único, y como cada uno lo crea otro (su padre), se forma un árbol de procesos con systemd (PID 1) en la raíz.
Justo después de un fork(), marca verdadero o falso.
- Padre e hijo ejecutan el mismo código.
- Padre e hijo usan la misma zona de memoria: si el hijo cambia una variable, el padre ve el cambio.
- Los archivos que el padre tenía abiertos quedan compartidos con el hijo.
- fork() devuelve 0 en el padre.
- Todo proceso se crea escribiendo una orden en la terminal.
Solución
- V — Padre e hijo ejecutan el mismo código.
- F — Padre e hijo usan la misma zona de memoria: si el hijo cambia una variable, el padre ve el cambio.
- V — Los archivos que el padre tenía abiertos quedan compartidos con el hijo.
- F — fork() devuelve 0 en el padre.
- F — Todo proceso se crea escribiendo una orden en la terminal.
El hijo es un duplicado del padre: mismo código, pero su propia copia de la memoria. Si el hijo hace contador++, el padre sigue con su valor. Los archivos abiertos sí se comparten.
fork() devuelve 0 al hijo y el PID del hijo al padre. Y no todo nace en la terminal: cualquier proceso puede crear otros con una llamada al sistema (systemd crea los servicios al arrancar).
Relaciona cada llamada con lo que hace.
| fork() | |
| exec() | |
| wait() | |
| exit() | |
| kill() | |
| CreateProcess() |
Definiciones:
- Aborta otro proceso
- Termina el proceso que la llama
- Sustituye el código del proceso por otro ejecutable
- Crea un hijo que es un duplicado del padre
- Espera a que termine un hijo
- Cambia la prioridad de un proceso
- Crea en Windows un proceso indicando su ejecutable
Solución
- fork() → Crea un hijo que es un duplicado del padre
- exec() → Sustituye el código del proceso por otro ejecutable
- wait() → Espera a que termine un hijo
- exit() → Termina el proceso que la llama
- kill() → Aborta otro proceso
- CreateProcess() → Crea en Windows un proceso indicando su ejecutable
En Unix, crear un proceso que ejecute otro programa son dos pasos: fork() (duplicar) y exec() (cambiar el código). En Windows, CreateProcess() lo hace en uno, indicando el ejecutable.
El hijo de bash (PID 3151) llama a exec() para ejecutar gcc. ¿Cuántos procesos nuevos se crean?
- Ninguno: el proceso 3151 sigue siendo el mismo, con el código de gcc
- Uno, con un PID nuevo
- Dos: uno para bash y otro para gcc
- Uno, pero con el mismo PID que bash (3150)
Solución
Respuesta: Ninguno: el proceso 3151 sigue siendo el mismo, con el código de gcc
exec() conserva el PID, el PCB y los archivos abiertos, y cambia el código y los datos por los del nuevo programa. Si exec() funciona, nunca vuelve: el código que la llamó ya no existe.
Para cada fragmento de C, ejecutado por un único proceso, escribe cuántos procesos hay al final (contando el original) y cuántas veces se imprime «x». Supón que fork() nunca falla.
| Fragmento | Procesos en total | Veces que se imprime x |
|---|---|---|
fork(); fork(); printf("x"); | ||
for (i = 0; i < 4; i++) fork(); printf("x"); | ||
if (fork() == 0) fork(); printf("x"); | ||
fork(); if (fork() == 0) exit(0); printf("x"); |
Solución
| Fragmento | Procesos en total | Veces que se imprime x |
|---|---|---|
fork(); fork(); printf("x"); | 4 | 4 |
for (i = 0; i < 4; i++) fork(); printf("x"); | 16 | 16 |
if (fork() == 0) fork(); printf("x"); | 3 | 3 |
fork(); if (fork() == 0) exit(0); printf("x"); | 4 | 2 |
Fila 1: el primer fork() deja 2 procesos y los dos hacen el segundo: 2 × 2 = 4. Fila 2: cada vuelta duplica a todos, 2⁴ = 16, y los 16 imprimen.
Fila 3: solo el hijo (al que fork() devuelve 0) hace el segundo fork(): original + hijo + nieto = 3. Fila 4: tras el primer fork() hay 2 procesos; cada uno crea un hijo con el segundo fork() (ya son 4), pero esos dos hijos hacen exit(0) antes del printf: solo imprimen los 2 primeros.
¿Qué devuelve fork() en el proceso padre cuando todo va bien?
- El PID del hijo que acaba de crear
- 0
- -1
- Su propio PID
Solución
Respuesta: El PID del hijo que acaba de crear
Un fork(), dos vueltas: el padre recibe el PID del hijo y el hijo recibe 0. Por eso el típico if (pid == 0) separa lo que hace cada uno.
Sobre cómo termina un proceso, marca verdadero o falso.
- Un proceso termina cuando llama a exit().
- Un proceso solo puede terminar si otro le envía kill().
- Si provoca una excepción, el SO puede decidir abortarlo.
- Un hijo termina en el momento en que su padre llama a wait().
- Un proceso zombi sigue ejecutando instrucciones indefinidamente.
Solución
- V — Un proceso termina cuando llama a exit().
- F — Un proceso solo puede terminar si otro le envía kill().
- V — Si provoca una excepción, el SO puede decidir abortarlo.
- F — Un hijo termina en el momento en que su padre llama a wait().
- F — Un proceso zombi sigue ejecutando instrucciones indefinidamente.
Termina con exit(), porque lo aborta otro con kill() o porque el SO lo aborta tras una excepción. wait() no mata a nadie: el padre espera a que el hijo acabe.
Un zombi ya terminó: no ejecuta nada, solo conserva su entrada (PID y estado de salida) hasta que el padre la recoja con wait().
¿Cuáles son los dos modelos de comunicación entre procesos (IPC)?
- Memoria compartida
- Paso de mensajes
- Interrupciones
- Cambio de contexto
- Planificación de largo plazo
Solución
Respuesta: Memoria compartida · Paso de mensajes
Dos modelos: memoria compartida y paso de mensajes. Los mecanismos concretos (tuberías, sockets, RPC…) son formas de implementarlos.
Completa los mecanismos clásicos de IPC.
Dos procesos pueden comunicarse mediante ____ (pipes), ____, zonas de memoria compartida, llamadas a procedimiento remoto (RPC) o, la forma menos eficiente, ____ normales.
Palabras:
- PCB
- ficheros
- interrupciones
- tuberías
- registros
- sockets
Solución
Dos procesos pueden comunicarse mediante tuberías (pipes), sockets, zonas de memoria compartida, llamadas a procedimiento remoto (RPC) o, la forma menos eficiente, ficheros normales.
Los ficheros funcionan, pero cada intercambio pasa por el disco: por eso son el mecanismo más lento. Tuberías y sockets son paso de mensajes.
¿Qué tiene cada hilo propio? Marca V si es propio del hilo y F si lo comparte con los demás hilos de su proceso.
- El contador de programa
- La pila (y su puntero de pila)
- Los registros de la CPU
- Las variables globales
- Los archivos abiertos
- El código del programa
Solución
- V — El contador de programa
- V — La pila (y su puntero de pila)
- V — Los registros de la CPU
- F — Las variables globales
- F — Los archivos abiertos
- F — El código del programa
Lo propio de un hilo es lo que hace falta para ejecutar por su cuenta: PC, registros, pila y su tiempo de CPU. Código, datos, archivos y recursos de E/S son del proceso y se comparten.
¿Qué ventajas tienen los hilos frente a crear varios procesos? Marca todas las correctas.
- Crear un hilo cuesta menos que crear un proceso
- Se comunican más fácilmente, porque comparten la memoria
- Consiguen más concurrencia con menos recursos
- Cambiar de un hilo a otro del mismo proceso puede ser más rápido
- Cada hilo tiene su propia copia de las variables globales
- Si un hilo falla, los demás hilos del proceso nunca se ven afectados
Solución
Respuesta: Crear un hilo cuesta menos que crear un proceso · Se comunican más fácilmente, porque comparten la memoria · Consiguen más concurrencia con menos recursos · Cambiar de un hilo a otro del mismo proceso puede ser más rápido
Las cuatro primeras son los beneficios de los apuntes. Precisamente por compartir memoria, crear hilos es más barato que crear procesos, y no al revés.
Relaciona cada modelo multihilo con su descripción.
| Muchos a uno | |
| Uno a uno | |
| Muchos a muchos | |
| Dos niveles |
Definiciones:
- Muchos hilos de usuario repartidos sobre varios hilos del núcleo
- Cada hilo de usuario tiene su hilo del núcleo; es el de Linux y Windows
- Como muchos a muchos, pero permite unir un hilo de usuario a uno del núcleo
- Cada hilo del núcleo ejecuta varios procesos pesados a la vez
- Muchos hilos de usuario sobre un solo hilo del núcleo; si uno se bloquea, se bloquean todos
Solución
- Muchos a uno → Muchos hilos de usuario sobre un solo hilo del núcleo; si uno se bloquea, se bloquean todos
- Uno a uno → Cada hilo de usuario tiene su hilo del núcleo; es el de Linux y Windows
- Muchos a muchos → Muchos hilos de usuario repartidos sobre varios hilos del núcleo
- Dos niveles → Como muchos a muchos, pero permite unir un hilo de usuario a uno del núcleo
Muchos a uno es el más antiguo (Solaris Green Threads, GNU Portable Threads) y casi no se usa: no aprovecha varios núcleos. Uno a uno da más concurrencia, a costa de limitar a veces el número de hilos.
En un sistema con hilos de usuario (gestionados por una biblioteca, sin que el núcleo los conozca), uno de los hilos hace una lectura de disco y se bloquea. ¿Qué pasa?
- Se bloquea el proceso pesado entero
- Solo se bloquea ese hilo; los demás siguen
- El SO crea otro hilo del núcleo para los demás
- El proceso termina con un error
Solución
Respuesta: Se bloquea el proceso pesado entero
Con hilos de usuario, el núcleo no sabe que el proceso tiene concurrencia interna: si un hilo se bloquea, se bloquea todo. Por eso hoy lo normal son los hilos del núcleo.
Como un hilo comparte la memoria y los recursos de su proceso, también se le llama proceso… (una palabra)
Solución
Respuesta: ligero
Proceso ligero (lightweight process), frente al proceso pesado, que es la aplicación entera con uno o varios hilos. A los hilos también se les llama hebras.
En las preguntas de contar procesos, no intentes adivinar con fórmulas. Dibuja el árbol: cada fork() que se ejecuta añade un proceso, y el truco está en ver quién llega a cada fork(). Si hay un if (fork() == 0), solo entra el hijo; si hay un exit(), ese proceso ya no llega al printf.
Preguntas de desarrollo
En el examen escrito de IC2 caen preguntas para explicar con tus palabras. Escribe tu respuesta en la caja antes de abrir la respuesta modelo y compárala con la lista de «lo que se valora».
Explica la diferencia entre programa y proceso. ¿Qué zonas tiene la memoria de un proceso y qué información guarda su PCB?
Solución
Respuesta modelo:
Un programa es un fichero ejecutable en el disco: una entidad pasiva. Un proceso es un programa en ejecución: una entidad activa que el SO crea con una llamada al sistema y a la que asigna recursos (memoria principal, CPU, E/S). Un mismo programa puede dar lugar a varios procesos.
La memoria de un proceso tiene cuatro zonas: text (código), data (variables globales), heap (memoria dinámica, que crece hacia arriba) y stack (pila con locales, parámetros y direcciones de retorno, que crece hacia abajo). text y data se copian del ejecutable.
El PCB es la estructura del SO con su estado, contador de programa, registros, información de planificación, de memoria, de E/S y archivos, y contable (PID, tiempo de CPU). Gracias a él el SO puede sacar el proceso de la CPU y reanudarlo después.
Lo que se valora:
- Programa pasivo frente a proceso activo (programa en ejecución)
- Las cuatro zonas de memoria con su contenido y qué se copia del ejecutable
- Al menos cinco campos del PCB
- Para qué sirve el PCB (cambio de contexto)
Si te falta tiempo, prioriza la definición y los campos del PCB: son lo que más se pregunta.
Dibuja o describe el diagrama de cinco estados de un proceso con sus transiciones y explica por qué no existe la transición de bloqueado a ejecución.
Solución
Respuesta modelo:
Estados: nuevo, preparado, en ejecución, bloqueado y terminado. Transiciones: nuevo → preparado (el SO lo admite); preparado → ejecución (el despachador lo elige); ejecución → preparado (interrupción, por ejemplo el temporizador); ejecución → bloqueado (pide una E/S o espera un evento); bloqueado → preparado (termina la E/S u ocurre el evento); ejecución → terminado (exit o aborto).
No existe bloqueado → ejecución porque cuando llega el evento puede haber otro proceso usando la CPU, y quien decide quién la usa es el planificador de corto plazo, que elige entre los preparados. El proceso despertado entra en la cola de preparados y espera su turno como los demás.
Lo que se valora:
- Los cinco estados con su significado
- Las seis transiciones con su causa
- Diferencia entre preparado (espera la CPU) y bloqueado (espera un evento)
- Justificación: al despertar vuelve a la cola de preparados y decide el planificador
Un dibujo limpio con las flechas etiquetadas suele valer más que un párrafo largo.
Escribes gcc practica.c -o practica en una terminal con bash. Explica qué procesos intervienen y qué hacen fork(), exec(), exit() y wait() hasta que vuelve a salir el prompt.
Solución
Respuesta modelo:
bash llama a fork(): el SO crea un hijo, duplicado de bash, con un PID nuevo. fork() devuelve el PID del hijo a bash y 0 al hijo. El hijo tiene el mismo código y una copia propia de la memoria, y comparte los archivos abiertos (la terminal).
El hijo llama a exec() con gcc: su código y sus datos se sustituyen por los de gcc, pero sigue siendo el mismo proceso, con el mismo PID. Mientras, bash llama a wait() y pasa a bloqueado.
Cuando gcc termina de compilar, llama a exit(0). Queda como zombi (ya no ejecuta, solo guarda su estado de salida) hasta que wait() de bash lo recoge. Entonces bash pasa a preparado, vuelve a la CPU y enseña el prompt.
Lo que se valora:
- fork() duplica y devuelve valores distintos a padre e hijo
- exec() cambia el código sin crear proceso ni cambiar el PID
- wait() bloquea al padre hasta que el hijo termina
- exit() termina el hijo y el padre recoge su estado
- Qué se copia (memoria) y qué se comparte (archivos abiertos)
Es la secuencia de cada orden que escribes en la terminal; si la cuentas con un ejemplo concreto se entiende mucho mejor.
Compara procesos e hilos: qué comparte un hilo con los demás hilos de su proceso, qué tiene propio, qué ventajas aporta y qué problema tienen los hilos de usuario en el modelo muchos a uno.
Solución
Respuesta modelo:
Un hilo (hebra o proceso ligero) es la unidad básica de ejecución dentro de un proceso. Cada hilo tiene su propio contador de programa, registros, pila y tiempo de CPU. Comparte con los demás hilos el código, los datos (variables globales, heap) y los recursos del SO (archivos abiertos, E/S).
Ventajas: se crean más rápido que los procesos, se comunican fácilmente porque comparten memoria, dan más concurrencia con menos recursos y cambiar de hilo puede ser más barato (no hay que vaciar cachés ni cambiar tablas de páginas).
Los hilos de usuario los gestiona una biblioteca y el núcleo no los conoce. En el modelo muchos a uno, todos van sobre un único hilo del núcleo: si uno hace una llamada bloqueante se bloquea el proceso entero, y no pueden ejecutarse en paralelo en varios núcleos. Por eso hoy se usa sobre todo el modelo uno a uno (Linux, Windows).
Lo que se valora:
- Qué es propio del hilo (PC, registros, pila) y qué se comparte (código, datos, archivos)
- Al menos tres ventajas frente a los procesos
- Hilos de usuario frente a hilos del núcleo
- El problema del bloqueo en muchos a uno y el paralelismo
Un esquema de un proceso con tres hilos (como el de spotify del artículo de teoría) resume media respuesta.
En la pregunta de fork() y exec(), un ejemplo concreto vale oro. «bash (PID 3150) hace fork(), el hijo 3151 hace exec() de gcc…» demuestra que lo entiendes mejor que tres definiciones seguidas.
Todo el tema en un dibujo
Antes del chuletario, el mapa entero. Si puedes explicar en voz alta cada línea de las seis cajas, el test de este tema está hecho:
Chuletario: procesos e hilos
Lo esencial en 30 segundos
- Proceso = programa en ejecución (activo). Programa = fichero (pasivo). Se crea con una llamada al sistema.
- Memoria: text (código) y data (globales) salen del ejecutable; heap (malloc) y stack (locales) nacen al ejecutar.
- PCB: estado, PC, registros, planificación, memoria, E/S y archivos, contabilidad. Nunca las locales ni el código.
- Estados: nuevo → preparado ⇄ ejecución → terminado; ejecución → bloqueado → preparado. Nunca bloqueado → ejecución.
- Cambio de contexto: el despachador, en modo núcleo, guarda en el PCB; es tiempo perdido.
- fork duplica (0 al hijo, PID del hijo al padre); exec cambia el código sin crear proceso; wait espera; exit termina.
- Hilo: propio PC, registros y pila; comparte código, datos y archivos.
Quiero saber… / Respuesta
| Quiero saber… | Respuesta |
|---|---|
| Qué espera un proceso preparado | La CPU |
| Qué espera un proceso bloqueado | Un evento: el fin de una E/S, un hijo… |
| Adónde va un proceso cuando termina su E/S | A preparado (no a ejecución) |
| Quién decide qué proceso usa la CPU | El planificador de corto plazo (PCP) |
| Quién hace el cambio de contexto | El despachador (dispatcher), en modo núcleo |
| Qué planificador hace swapping | El de medio plazo (PMP) |
Qué devuelve fork() al padre / al hijo | El PID del hijo / 0 (y -1 si falla) |
Cuántos procesos crea exec() | Ninguno |
Qué se copia con fork() | La memoria (cada uno la suya) |
Qué se comparte con fork() | El código y los archivos abiertos |
| Qué es un zombi | Un hijo terminado cuyo padre aún no ha hecho wait() |
| Los dos modelos de IPC | Memoria compartida y paso de mensajes |
| El modelo multihilo de Linux y Windows | Uno a uno |
Plantillas para contar procesos
| Fragmento | Procesos en total | Por qué |
|---|---|---|
fork(); repetido n veces seguidas | 2ⁿ | Cada fork() lo ejecutan todos los que existen |
for (i = 0; i < n; i++) fork(); | 2ⁿ (2ⁿ − 1 hijos) | Igual que n fork() seguidos |
if (fork() == 0) fork(); | 3 | Solo el hijo hace el segundo |
if (fork() > 0) fork(); | 3 | Solo el padre hace el segundo |
fork(); if (fork() == 0) exit(0); | 4, pero solo 2 siguen vivos | Los dos nietos terminan nada más nacer |
Estados: de dónde a dónde
| Estado | Se llega desde… | Se sale hacia… |
|---|---|---|
| Nuevo | (lo crea fork()) | preparado |
| Preparado | nuevo, ejecución, bloqueado | ejecución |
| Ejecución | preparado | preparado, bloqueado, terminado |
| Bloqueado | ejecución | preparado |
| Terminado | ejecución | (el SO le retira los recursos) |
Si la pregunta dice… / Piensa en…
| Si la pregunta dice… | Piensa en… |
|---|---|
| «memoria secundaria» para ejecutarse | Falso: memoria principal |
| «se crea con una rutina de servicio a interrupción» | Falso: con una llamada al sistema |
| «el cambio de contexto se hace en modo usuario» | Falso: modo núcleo |
| «el módulo se llama conmutador» | Falso: despachador |
| «crear hilos cuesta más que crear procesos» | Falso: al revés |
«el hijo termina cuando el padre hace wait()» | Falso: wait() solo espera |
| «un hilo tiene sus propias variables globales» | Falso: las comparte |
| «con hilos de usuario, si un hilo se bloquea…» | Se bloquea el proceso pesado entero |
Antes de entregar, pregúntate
- ¿He distinguido bien entre preparado (espera la CPU) y bloqueado (espera un evento)?
- En las de contar procesos, ¿he dibujado el árbol y mirado quién llega a cada
fork()? - En las múltiples del PCB y de los hilos, ¿he marcado solo lo que es propio de verdad?
- ¿He leído bien si la frase compara procesos con hilos o hilos con procesos?
Si quieres repasar algo, vuelve a la teoría de procesos e hilos, y si te apetece verlo funcionar en tu terminal, los ejercicios de Procesos en C tienen fork(), exec() y wait() de verdad. El siguiente tema es la planificación de la CPU: con qué criterio elige el planificador a quién darle el turno y cómo se dibuja en un Gantt.
¿Te ha servido este artículo? Así puedes apoyar SergioLearns →
¿Listo para el examen?Simulacro del examen de teoría de IC2 — primer parcial, segundo parcial o convocatoria, con tu nota real y el repaso de cada fallo (como si estuvieras en el aula)


