当旧进程在 C 中终止时创建一个新的子进程

Creating a new child process when old one is terminated in C

我已经包含了创建一系列子进程来划分任务工作的代码。它有一个随机的机会终止(由它调用 abort() 的 word_count 函数处理)并且在这个事件上,它应该创建一个新的子进程来替换它。但是,该程序在读取时被阻止。我知道这段代码很乱,但我想在清理之前了解问题所在。

    int pipes[nChildProc][2]; //pipe fd[0] is read end, fd[1] is write end
    long child_f_size = fsize / nChildProc;
    pid_t pids[nChildProc];

    //start dividing the work among child processes
    for(int i = 0; i < nChildProc; ++i) {
        //srand(time(NULL));
        //int crash = ((rand() / RAND_MAX + 1.0) < crashRate) ? 1 : 0;
        if(pipe(pipes[i]) != 0) {
            printf("Failed to create pipe.\n");
            exit(1);
        }

        pid_t pid = fork();
        FILE *child_fp;
        pids[i] = pid;

        if(pid < 0) {
            printf("Failed to create child process.\n");
            exit(1);
        }
        else if(pid == 0) { //child process
            count_t temp_count = readFromFile(child_fp, fsize, child_f_size, char* name, int i, int nChildProc);

            //IPC with the main process
            if(write(pipes[i][1], &temp_count, sizeof(temp_count)) == -1)
                printf("failed to write to pipe.\n");

            close(pipes[i][1]);
            close(pipes[i][0]);
            exit(0); //deallocate process' memory space
        }
    }

    //wait for a children to finish
    int ret, status, i = 0;
    while(wait(NULL) != -1) { // while there are children to wait on
        ret = waitpid(pids[i], &status, WUNTRACED);

        if(ret == -1) {
            continue;
        }

        if(ret != 0) {// didn't exit normally
            if(pipe(pipes[i]) != 0) {
                printf("Failed to create pipe.\n");
                exit(1);
            }

            pid_t pid = fork();
            FILE *child_fp;
            pids[i] = pid;

            if(pid < 0) {
                printf("Failed to create child process.\n");
                exit(1);
            }
            else if(pid == 0) { //child process
                count_t temp_count = readFromFile(child_fp, fsize, child_f_size, char* name, int i, int nChildProc);

                //IPC with the main process
                if(write(pipes[i][1], &temp_count, sizeof(temp_count)) == -1)
                    printf("failed to write to pipe.\n");

                close(pipes[i][1]);
                close(pipes[i][0]);
                exit(0); //deallocate process' memory space
            }
        }

        i = (i + 1) % nChildProc;//loop back to detect more processes that were terminated
    }

    long bytes;
    count_t temp;
    temp.linecount = 0;
    temp.wordcount = 0;
    temp.charcount = 0;

    //add up all the values from children to count
    printf("time to read.\n");
    for(unsigned int j = 0; j < nChildProc; ++j) {
        if((bytes = read(pipes[j][0], &temp, sizeof(temp))) < 0) {//blocked here
            printf("Failed to read from pipe {%d}.\n", j);
            exit(1);
        }

        if(bytes != 0) {
            count.linecount += temp.linecount;
            count.wordcount += temp.wordcount;
            count.charcount += temp.charcount;
        }

        close(pipes[j][1]);
        close(pipes[j][0]);
    }

几个问题跳出来了:

  1. if(ret != 0) {// didn't exit normally 您混淆了 ret(pid)和 status(child 的退出代码)

  2. 您不能对一个进程调用 wait 两次,因为调用 wait 允许系统释放与该进程关联的资源。关于如何重写此代码,您有多种选择:

        while(wait(NULL) != -1) { // while there are children to wait on
            ret = waitpid(pids[i], &status, WUNTRACED);

一个简单的方法是使用 wait 然后在数组中查找它属于哪个索引。

    while((pid = wait(&status)) {
        if (pid == -1) {  // no children to wait on
            break;
        }
        for(int i = 0; i < nChildProc; ++i) {
            if (pid == pids[i]) break;
        }
        if (i >= nChildProc) {
            unexpected_pid_do_something_smart();
        }
        // Leave the rest of the loop the same

注意:我没有编译或测试上面的代码。