C - 最后一个孩子从未接触过信号

时间:2016-03-04 02:23:54

标签: c pipe fork ipc fifo

我的代码分叉n个进程。当到达最后一个进程时,它通过FIFO向顶级进程发送消息以终止所有进程。我的代码工作得很好,除了最后一个进程永远不会达到我的信号并且永远不会被顶级进程杀死。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/signal.h>
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
#define MAX_BUF 1024

int *ptr;
int numprocs;

void signal_handler(int sig){
    int currpid = getpid();
    int lev;
    int i;
    for(i = 1; i < numprocs; i++){
        if(ptr[i] == currpid){
            lev = numprocs - i;
            break;
        }
    }

    fprintf(stdout,"EXITING: Level %d process with pid=%d, child of ppid=%d.\n", lev, ptr[i], ptr[i-1]);

    exit(0);
}


int main(int argc, char **argv){
    numprocs = atoi(argv[1]);
    int lev = numprocs;
    bool x = true;

    //create shared memory
    const int SIZE = numprocs * sizeof(int);
    const char *name = "dleggio1OS";
    int shm_fd;
    shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    ftruncate(shm_fd, SIZE);
    ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
    *ptr = getpid();

    //create unnamed pipe
    int pfds[2];
    char buf[30];
    if(pipe(pfds) == -1){
        perror("pipe");
        exit(1);
    }

    //create fifo
    int fd;
    char *myfifo = "/tmp/dleggio1fifo";
    mkfifo(myfifo, 0666);

    pid_t pid = fork();

    if(pid == 0){ //first child ..... keep forking
        //read unnamed pipe
        close(pfds[1]);
        if(read(pfds[0], buf, 3) <= 0){
            perror("child");
            exit(1);
        }
        int check = atoi(buf);
        fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, getpid(), getppid());
        //write to shared memory
        ptr[numprocs - check] = getpid();
        signal(SIGUSR1,signal_handler);
        int i;
        lev--;
        for(i = 2; i < numprocs; i++){
            //create named pipe
            int pfds[2];
            char buf[30];
            if(pipe(pfds) == -1){
                perror("pipe");
                exit(1);
            }

            lev--;
            pid_t pid;

            if((pid = fork()) < 0){

                perror("fork");

                exit(1);
            }

            else if(pid == 0){

                //update shared memory
                ptr[i] = getpid();

                //read from named pipe
                close(pfds[1]);
                if(read(pfds[0], buf, 3) <= 0){
                    perror("child");
                    exit(1);
                }
                int check = atoi(buf);
                fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, getpid(), getppid());
                if(check == 1){

                    //write to fifo
                    fd = open(myfifo, O_WRONLY);
                    write(fd,"leaf",sizeof("leaf"));
                    close(fd);


                    unlink(myfifo);
                    signal(SIGUSR1,signal_handler);

                }
                signal(SIGUSR1,signal_handler);

            }

            else{
                //write to named pipe
                close(pfds[0]);
                char hold[3];
                sprintf(hold,"%d",lev);
                if(write(pfds[1], hold, 3) <= 0){
                    perror("parent");
                    exit(1);
                }

                wait(NULL);

            }

        }

    }

    else{ //top level
        fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", lev, getpid(), getppid());
        //write to unnamed pipe
        lev--;
        close(pfds[0]);
        char hold[3];
        sprintf(hold,"%d",lev);
        if(write(pfds[1], hold, 3) <= 0){
            perror("parent");
            exit(1);
        }
        //read from fifo
        char buff[MAX_BUF];
        fd = open(myfifo,O_RDONLY);
        read(fd,buff,MAX_BUF);
        close(fd);
        unlink(myfifo);
        char *comp = "leaf";

        if(strcmp(buff,comp) == 0){
            int j;
            for(j = 0; j < numprocs; j++) printf("%d\n",ptr[j]);
            for(j = 1; j < numprocs; j++) kill(ptr[j],SIGUSR1);
            shm_unlink(name);
            fprintf(stdout,"EXITING: Level %d process with pid=%d, child of ppid=%d.\n", numprocs, getpid(), getppid());
            exit(0);
        }




    }


}

输出:

./prog1 4
ALIVE: Level 4 process with pid=5129, child of ppid=4692.
ALIVE: Level 3 process with pid=5130, child of ppid=5129.
ALIVE: Level 2 process with pid=5131, child of ppid=5130.
ALIVE: Level 1 process with pid=5132, child of ppid=5131.
5129
5130
5131
5132
EXITING: Level 4 process with pid=5129, child of ppid=4692.
EXITING: Level 3 process with pid=5130, child of ppid=5129.
EXITING: Level 2 process with pid=5131, child of ppid=5130.

0 个答案:

没有答案