fork, exec y contar «Hello!»
La pregunta 1 de los dos E1 de 2024 fue la misma idea: ¿cuántas veces se imprime «Hello!»? (3 pts). Se resuelve dibujando el árbol de procesos y anotando, en cada proceso, el valor de las variables que decide cada if.
Las 5 reglas
Sección titulada «Las 5 reglas»fork()devuelve 0 en el hijo y el pid del hijo en el padre. Desde ese punto ambos ejecutan la misma línea siguiente.- El hijo recibe una copia de toda la memoria: variables, buffers de
stdio, semáforos y mutex con su valor actual. Nada se comparte después del fork (salvo memoria compartida explícita). - Solo se copia el hilo que llamó a
fork. execvreemplaza el programa: lo que sigue en el código viejo no se ejecuta, y el nuevo programa empieza enmaincon otroargc/argv.- Los hilos comparten la memoria de su proceso. Si el hilo recibe
&pid, lee elpidde su proceso.
Qué se hereda y qué no
Sección titulada «Qué se hereda y qué no»| Se hereda (se copia) | No se hereda |
|---|---|
| text, data, BSS, heap y stack (copias independientes) | el PID (el hijo tiene uno nuevo) y el PPID |
| descriptores de archivo abiertos, que comparten el offset | señales pendientes |
| credenciales (UID/GID), entorno, directorio actual | locks de archivos (fcntl) y memoria bloqueada (mlock) |
| handlers y máscara de señales | timers y alarmas; E/S asíncrona (AIO) |
| tablas de páginas (con COW), contexto de hardware, estructuras IPC | ajustes de semop (semundo) |
En el ejemplo fork2.c de clase (static int g = 5; int loc = 9;), el hijo hace loc++; g-- e imprime loc=10 g=4, y el padre hace loc--; g++ e imprime loc=8 g=6. Son copias: nada de lo que haga uno afecta al otro.
fork en Linux: clone() y copy-on-write
Sección titulada «fork en Linux: clone() y copy-on-write»- En Linux,
fork()esclone()con ciertos flags, y usa COW (copy-on-write): padre e hijo comparten las páginas marcadas como solo lectura, y una página se duplica recién cuando alguno la escribe. El costo real deforkes copiar las tablas de páginas y crear eltask_struct. - Si el hijo hace
execenseguida, las páginas nunca se copian. Por esofork+execes barato. (vfork=CLONE_VFORK: el padre se suspende hasta que el hijo haceexecoexit.) - Un hilo en Linux es un
cloneconCLONE_VM(comparte el espacio de direcciones), además deCLONE_FS,CLONE_FILES,CLONE_SIGHANDyCLONE_THREAD. Para el kernel, un hilo es simplemente un proceso que comparte recursos. - Árbol de procesos: cada
task_structapunta a suparenty tiene una lista dechildren.init_taskes estático, yfor (t = current; t != &init_task; t = t->parent);sube hasta init. La lista de tareas es circular y doblemente enlazada (for_each_process).
Simulador
Sección titulada «Simulador»Árbol de procesos: ¿cuántos «Hello!»?
Avanza evento por evento. Recuerda: fork copia el proceso entero (variables y semáforos incluidos, pero solo el hilo que llamó), execv reemplaza la imagen y exit lo termina.
0void *thread_print(void *value) {1 if (*((pid_t *) value))2 printf("Hello!\n");3}4int main() {5 pid_t parent;6 pid_t grandparent = fork();7 if (!grandparent) {8 parent = fork();9 printf("Hello!\n");10 if (!parent) exit(0);11 } else {12 pthread_create(&t, NULL, thread_print, &grandparent);13 pthread_join(t, NULL);14 }15 printf("Hello!\n");16 parent = fork();17 pthread_create(&t2, NULL, thread_print, &parent);18 pthread_join(t2, NULL);19}
- P
Ejercicio del E1 2024-II
Sección titulada «Ejercicio del E1 2024-II»Con el código de la segunda pestaña: argc = 1 al inicio, execv("./hello-fork-exec", {"1","2"}) y un semáforo iniciado en 1 después del segundo fork.
Ver solución
4 veces.
- P tiene
argc = 1→ no entra al primerif. - P hace fork → H1 (pid = 0) hace
execvy el programa reinicia conargc = 2→ imprime (1) y termina. - P hace fork → H2. Cada proceso hace su propio
sem_init(&mutex, 0, 1): son semáforos distintos (copias). - El thread de P hace
sem_wait(1→0), imprime (2) y hacesem_postporquepid ≠ 0. - El thread de H2 hace
sem_wait(1→0), imprime (3) y no hacesem_postporque supid = 0. - El main de P hace
sem_wait(1→0) → imprime (4). El main de H2 hacesem_waitcon valor 0 → se bloquea para siempre.
Autoevaluación
0/5 correctas · 0 respondidasfork(); fork(); fork();?pid = fork();, ¿qué vale pid en el hijo?fork() desde el hilo 2. ¿Cuántos hilos tiene el hijo?execv tiene éxito, ¿qué pasa con las líneas que lo siguen?sem_t s iniciado en 0 antes de fork. El padre hace sem_post(&s). ¿Se despierta un sem_wait(&s) del hijo?Fuente ·for_partial/E1_OS_2024_I__Respuestas_.pdf (P1) · for_partial/E1_OS_2024_II__Solucionario_.pdf (P1) · código del curso so/OST-02-Processes_Syscalls_Signals · prueba propia verif_parcial/hello24.c, hellofe.c