Programación de Procesos en C: Ejemplos Prácticos de Fork, Sys, Huérfanos y Atexit
Clasificado en Informática
Escrito el en
español con un tamaño de 4,55 KB
Introducción a la Gestión de Procesos en C
A continuación se presenta una serie de ejemplos prácticos en lenguaje C para comprender la creación, control y gestión de procesos en sistemas operativos tipo Unix.
Ejemplo Básico de Bifurcación (Fork)
El siguiente fragmento ilustra la estructura básica para el uso de la función fork() y la evaluación de sus posibles retornos.
#include <stdio.h>
#include <stdlib.h>
int main() {
int i = 0;
switch(fork()) {
case -1: /* error */ break;
case 0: /* hijo */ break;
default: /* padre */ break;
}
exit(0);
}Ejecución de Comandos del Sistema
Este ejemplo muestra cómo utilizar la función system() para invocar comandos del sistema operativo, combinándola con getenv() para obtener variables de entorno.
#include <stdio.h>
#include <stdlib.h>
int main() {
int salida;
char comando[100];
sprintf(comando, "/bin/ps -fu %s", getenv("USER"));
salida = system(comando);
exit(salida);
}Sincronización Básica con Fork y Sleep
Ejemplo elemental para diferenciar el flujo de ejecución entre el proceso hijo y el proceso padre utilizando temporizadores con sleep().
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
if (fork() == 0) {
/* hijo */
sleep(1);
} else {
/* padre */
sleep(1);
}
exit(0);
}Demostración de un Proceso Huérfano
Cuando un proceso padre termina antes que su hijo, este último se convierte en un proceso huérfano, siendo adoptado por el proceso init.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
printf("Ejemplo de proceso huérfano.\n");
printf("Inicio del proceso padre. PID=%d\n", getpid());
if (fork() == 0) {
printf("Inicio proceso hijo. PID=%d, PPID=%d\n", getpid(), getppid());
sleep(1);
printf("El proceso queda huérfano. PID=%d PPID=%d\n", getpid(), getppid());
} else {
printf("Continuación del padre. PID=%d\n", getpid());
}
printf("Fin del proceso %d\n", getpid());
exit(0);
}Manejo de Señales y Espera de Hijos (Waitpid)
Este código avanzado demuestra el uso de signal() para ignorar interrupciones (como CTRL-C) y el uso de waitpid() junto con macros para evaluar el estado de salida del hijo.
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
int main() {
pid_t id_padre, id_hijo;
int estado;
printf("Inicio proceso padre. PID=%d\n", getpid());
id_padre = getpid();
if ((id_hijo = fork()) == 0) {
printf("Inicio proceso hijo. PID=%d, PPID=%d\n", getpid(), id_padre);
sleep(3);
printf("Salida proceso hijo. PID=%d\n", getpid());
exit(getpid() > id_padre); /* 1, si PID > PPID */
} else {
signal(SIGINT, SIG_IGN); /* Ignorar CTRL-C */
while (waitpid(id_hijo, &estado, 0) != id_hijo);
if (WIFSIGNALED(estado))
printf("El proceso hijo ha recibido la señal %d\n", WTERMSIG(estado));
if (WIFEXITED(estado)) {
printf("Estado de salida del proceso hijo: %d\n", WEXITSTATUS(estado));
if (WEXITSTATUS(estado) == 1)
printf("PID hijo > PID padre.\n");
else
printf("PID padre > PID hijo.\n");
}
printf("Fin del proceso %d\n", getpid());
exit(0);
}
}Uso de Atexit para Rutinas de Salida
La función atexit() permite registrar funciones que se ejecutarán automáticamente al finalizar el programa de forma normal.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int ciclo = 0;
void salida(void);
int main() {
int n;
srand(time(NULL));
atexit(salida);
printf("Ejemplo de atexit.\n");
for (ciclo = 1; ciclo < 255; ciclo++) {
n = rand() % 50000;
printf("%d-%d\t", ciclo, n);
if (n > 30000)
exit(1);
}
exit(0);
}
void salida(void) {
printf("\nEl ciclo ha dado %d vueltas.\n", ciclo);
printf("Hasta luego Proceso.\n");
}