简体   繁体   English

在 C 中终止旧子进程时创建新子进程

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

I've included code that creates a series of child processes to divide the work for a task.我已经包含了创建一系列子进程来划分任务工作的代码。 There's a random chance for it to terminate (handled by the word_count function from which it calls abort()) and on this event, it should create a new child process to replace it.它有一个随机的机会终止(由它调用 abort() 的 word_count function 处理),在这个事件中,它应该创建一个新的子进程来替换它。 However, the program is being blocked on the read.但是,该程序在读取时被阻止。 I know this code is messy, but I want understand the problem before cleaning it up.我知道这段代码很乱,但我想在清理之前了解问题。

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

A couple of issues jump out:有几个问题跳出来:

  1. if(ret != 0) {// didn't exit normally you've confused ret (which is the pid) for status (which is the exit code of the child) if(ret != 0) {// didn't exit normally你混淆了ret (这是 pid)和status (这是孩子的退出代码)

  2. You can't call wait on a process twice, since calling wait allows the system to release the resources associated with the process.您不能对进程调用两次 wait,因为调用 wait 允许系统释放与该进程关联的资源。 You have several options on how to rewrite this code:关于如何重写此代码,您有多种选择:

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

One easy way is to use wait then lookup in the array which index it belongs to.一种简单的方法是使用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

Note: I didn't compile or test the above code.注意:我没有编译或测试上面的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM