← Arquitectura Cliente-Servidor

Clase 04

Mtro. Carlos Alberto Román Zamitiz · 3 sep 2026 · Tema 1 — strerror() y perror(), control de flujo de fork(), procesos huérfanos y reapers, y la familia de funciones exec.

En corto

🎯 Reglas y conceptos clave

strerror() y los códigos de error de Linux

strerror(n) — "devuelve el mensaje de sistema correspondiente al código que le pasas como parámetro". El prefijo str es por string: devuelve la cadena de texto asociada al código numérico. Análisis de programa03_codigos_sistema.c:

int i;
for (i = 0; i <= 150; i++)          /* el límite se puede subir a 200 para probar */
    printf("%d: %s\n", i, strerror(i));

%d (o %i) se reemplaza con el entero i; %s con el string que devuelve strerror(i).

perror() — mensaje de error personalizado

Recibe una cadena personalizada; si la instrucción anterior generó error, perror toma esa cadena, le añade automáticamente ": " y concatena a la derecha el mensaje de error estándar del sistema. La P es de "personalizar".

Ejemplo: si un fork() falla, perror("fork") imprime fork: <mensaje del sistema>.

Control de flujo de fork()

Con condicionales, fork() abre tres caminos: el de error, el del hijo y el del padre.

Estilo compacto (paréntesis anidados):

if ((child = fork()) == -1) { ... }

El compilador lo resuelve así: 1) se invoca fork(); 2) su valor de retorno se asigna a child; 3) se compara child con -1.

Estilo descompuesto ("camino largo", prioriza claridad sobre rendimiento):

pid_t ch;
ch = fork();
if (ch == -1) { ... }

Documentación oficial y retorno de fork()

exit() y macros de salida

Cuando una llamada crítica (fork(), exec()) devuelve -1, se usa exit() para terminar el programa de inmediato y no seguir ejecutando código.

Procesos huérfanos, adopción y reapers

Al correr programa08, la salida muestra in parent antes que in child, y el hijo, al llamar getppid(), obtiene 1 aunque su padre real era otro.

La familia de funciones exec

No existe exec "a secas": es una familia de seis funciones que empiezan con esa palabra y añaden 1 o 2 letras que definen su comportamiento.

LetraSignificado
L (list)Los argumentos se escriben como lista explícita separada por comas, terminada en NULL o (char *)0.
V (vector)Los argumentos van en un arreglo de punteros, también terminado en puntero nulo.
E (environment)Permite pasar un vector de variables de entorno propias, válidas solo durante la ejecución del nuevo proceso.
P (PATH)No requiere ruta absoluta: lee la variable PATH y busca el ejecutable en los directorios del sistema (/bin, /usr/bin…).

Reemplazo de imagen y "argumento cero"

A diferencia de fork() (que duplica), cuando exec tiene éxito la imagen del proceso original en memoria se destruye y se reemplaza por completo por la del nuevo programa. El proceso original muere en ese punto y no recupera el control.

En C, argv[0] debe ser el nombre del ejecutable, por eso la cadena del comando aparece repetida:

execl("/bin/ls", "ls", "-l", "/", (char *)0);
/*     ^ruta      ^arg0 ^arg1 ^arg2  ^fin de lista */

Manejo de errores y código inalcanzable

Si el comando no existe o está mal escrito, exec falla, devuelve -1 y el proceso original sigue ejecutando las líneas de abajo. En una llamada exitosa, en cambio, esas líneas son inalcanzables (el proceso ya fue reemplazado).

Regla obligatoria — envolver en if y terminar si devuelve -1:

if (execl("/bin/ls", "ls", "-l", "/", (char *)0) == -1) {
    perror("execl");
    exit(EXIT_FAILURE);
}

Demo en terminal — programa10.c

gcc programa10.c -o programa10

Cierre

Sin pase de lista y sin tarea formal de entrega. Tarea moral: repasar la familia exec, con énfasis en execl. El profesor termina de calificar la Tarea 2 durante el fin de semana. La próxima sesión (martes) arranca el Tema 2: Estados de proceso.

Pendiente / próxima clase

Contexto — no examen

Teoría general de procesos, ejemplos en C y los programas del profesor están en el Tema 1.