C Programming: Mastering Unix Processes and IPC

Process Management with Grep

#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
    int i, pid;
    if (argc < 2) {
        fprintf(stderr, "Uso: padre [<archivo>]+\n");
        return EXIT_FAILURE;
    }
    for (i = 1; i < argc; i++) {
        switch (pid = fork()) {
            case -1:
                fprintf(stderr, "Error al crear el hijo\n");
                return EXIT_FAILURE;
            case 0:
                execlp("wc", "wc", "-l", argv[i], NULL);
                fprintf(stderr, "Error en execlp\n");
                exit(EXIT_FAILURE);
            default:
                printf("Inicio hijo %d con %s.\n", pid, argv[i]);
                break;
        }
    }
    for (i = 1; i < argc; i++) {
        pid = wait(NULL);
        printf("Fin hijo %d.\n", pid);
    }
    return EXIT_SUCCESS;
}

Parent Sending Signals to Children

#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int cont = 0;
int numHijos;

void manejador(int num) {
    signal(SIGINT, manejador);
    cont++;
    printf("Recibidas %d señales.\n", cont);
    if (cont == numHijos) {
        _exit(EXIT_SUCCESS);
    }
}

int main(int argc, char *argv[]) {
    int i;
    if (argc != 2) {
        fprintf(stderr, "Uso: padre <num_hijos>\n");
        return EXIT_FAILURE;
    }
    numHijos = atoi(argv[1]);
    if (numHijos <= 0) {
        fprintf(stderr, "Error: numero de hijos no valido\n");
        return EXIT_FAILURE;
    }
    if (signal(SIGINT, manejador) == SIG_ERR) {
        fprintf(stderr, "Error al registrar el manejador\n");
        return EXIT_FAILURE;
    }
    for (i = 0; i < numHijos; i++) {
        switch (fork()) {
            case -1:
                fprintf(stderr, "Error al crear el hijo\n");
                return EXIT_FAILURE;
            case 0:
                execl("./hijoexamen3", "hijoexamen3", NULL);
                fprintf(stderr, "Error en execl\n");
                exit(EXIT_FAILURE);
            default:
                break;
        }
    }
    while (1) { pause(); }
    return EXIT_SUCCESS;
}

Child Process Signal Handler

#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, char *argv[]) {
    printf("Señal enviada a %d por %d.\n", getppid(), getpid());
    if (kill(getppid(), SIGINT) == -1) {
        fprintf(stderr, "Error al enviar la señal\n");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Anonymous Pipes Implementation

#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
    int i, fd[2];
    char c;
    if (argc < 2) {
        fprintf(stderr, "Uso: padre [<cadena>]+\n");
        return EXIT_FAILURE;
    }
    if (pipe(fd) == -1) {
        fprintf(stderr, "Error al crear la tuberia\n");
        return EXIT_FAILURE;
    }
    for (i = 1; i < argc; i++) {
        switch (fork()) {
            case -1:
                fprintf(stderr, "Error al crear el hijo\n");
                return EXIT_FAILURE;
            case 0:
                close(1);
                dup(fd[1]);
                execl("./hijoexamen2", "hijoexamen2", argv[i], NULL);
                fprintf(stderr, "Error en execl\n");
                exit(EXIT_FAILURE);
            default:
                break;
        }
    }
    close(fd[1]);
    for (i = 1; i < argc; i++) {
        if (read(fd[0], &c, 1) != 1) {
            fprintf(stderr, "Error al leer de la tuberia\n");
            return EXIT_FAILURE;
        }
        printf("Fin hijo: %c\n", c);
        wait(NULL);
    }
    return EXIT_SUCCESS;
}

Child Process Logic

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Uso: hijo <cadena>\n");
        return EXIT_FAILURE;
    }
    printf("%c", argv[1][0]);
    return EXIT_SUCCESS;
}

Parent-Child Signal Communication

#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
    int i, numHijos;
    if (argc != 2) {
        fprintf(stderr, "Uso: padre <num_hijos>\n");
        return EXIT_FAILURE;
    }
    numHijos = atoi(argv[1]);
    if (numHijos <= 0) {
        fprintf(stderr, "Error: numero de hijos no valido\n");
        return EXIT_FAILURE;
    }
    pid_t pids[numHijos];
    for (i = 0; i < numHijos; i++) {
        switch (pids[i] = fork()) {
            case -1:
                fprintf(stderr, "Error al crear el hijo\n");
                return EXIT_FAILURE;
            case 0:
                execl("./hijo", "hijo", NULL);
                exit(EXIT_FAILURE);
            default:
                break;
        }
    }
    for (i = 0; i < numHijos; i++) {
        sleep(1);
        if (kill(pids[i], SIGINT) == -1) {
            fprintf(stderr, "Error al enviar la señal\n");
            return EXIT_FAILURE;
        }
        wait(NULL);
    }
    return EXIT_SUCCESS;
}