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");
}

Entradas relacionadas: