如何在传递子控件之前列出所有子pid?

时间:2019-01-22 21:53:55

标签: c multithreading process fork wait

我有一个作业,教授在将控制权传递给子进程之前要求父进程打印每个子进程的进程ID。

我试图做这样的事情:

pid_t cpids[5]; //I want to create 5 child processes
int n = 0;

do {
    cpids[n++] = fork();
} while(cpids[n] > 0 && n < 5) ; //This doesn't fork 5 times

//print all the child pids
printf("The child processes are: %d, %d, %d, %d, %d\n", cpids[0]..);
//(I know this would be printed multiple times, I'm just trying to explain what I need)

//then after printing the ids, tell child processes what to do
for(int i = 0; i < 5; i++) {

    //error
    if(cpids[i] < 0) {
        printf("There was an error with fork()\n");
        exit(1);
    }

    //child process
    else if(cpids[i] == 0) {
    //...reads from pipe sent from parent process
    }

    //parent process
    //sends message through pipe to child process
    //waits for child to terminate
}

所以这绝对不起作用:)。有没有更简单的方法来分叉进程而无需立即给出指示?谢谢!

//更新

所以我知道我做错了fork()事情。这是我的原始代码:

for(int i = 0; i < 5; i++) {
    //error
    if((pid = fork()) < 0) {
        printf("There was an error with fork()\n");
        exit(1);
    }

    //child process
    else if(pid == 0) {
        pid = getpid();
        close(fd[i][1]);

        //read starting position from parent process
        len = read(fd[i][0], &fpos, sizeof(fpos));

        if(len > 0) {
            doChild(numArray, fpos, i);
        }

        printf("id: %d\n", pid);
        _exit(1);
    } 

    //parent process
    else {
        close(fd[i][0]);
        fpos = (SIZE/NUM_CHILD) * i;
        write(fd[i][1], &fpos, sizeof(fpos));

        if ( waitpid(-getpid(), &status, 0) != -1 ) {
            if ( WIFEXITED(status) ) {
                int returned = WEXITSTATUS(status);
                printf("child id: %d ended with status %d\n\n", pid, returned);
            }
        }

        else {
            perror("waitpid() failed");
            exit(EXIT_FAILURE);
        }
    }

}

但是,父进程必须等待子进程终止,然后才能启动另一个子进程。我无法在所有子进程开始运行之前获取它们。我基本上是在寻找一种方法来创建我需要的所有子进程,也许让它们在创建后立即进入睡眠状态,然后在继续之前从父进程中打印出所有pid。

2 个答案:

答案 0 :(得分:1)

您似乎完全错过了fork的要点。这是一个非常特殊的函数-它返回0或非负整数或-1。分叉之后,您需要做的第一件事就是检查返回值。

如果它是非负数,则意味着您正在父母中执行,您可以继续您的父母事务。返回值是刚刚生成的子进程的PID。

如果它是-1,则有一个错误(非常奇怪的情况),如果它是0,则意味着您现在正在子进程中执行,并且您应该执行其他操作-哪个子进程是有望做到。

任何fork结果没有立即通过父分支进行检查的子代码始终是错误代码。

答案 1 :(得分:1)

我并不是真的想为您完成任务,但是我建议从类似以下内容开始:

void child_func(int readfd) {
    // read from readfd and do whatever
}

void do_fork(pid_t *childpid, int *pipefd) {
    int pipefds[2];
    pid_t pid;
    pipe(pipefds, 0);
    if ((pid = fork()) == 0) {
        child_func(pipefds[0]);
        exit(0);
    } else {
        *childpid = pid;
        *pipefd = pipefds[1];
    }
}

int main() {
    int i;
    pid_t children[5];
    int pipes[5];
    for (i = 0; i < 5; ++i) {
        do_fork(&children[i], &pipes[i]);
    }
    // whatever
    return 0;
}

如果您的child_func在开始时从文件描述符读取,它将阻塞,直到父对象写入其他5个描述符。这将使您有机会打印出pid或其他内容,然后告诉他们该怎么做。如果您不完全了解手册,请查看“管道”和“叉子”的手册页。我希望这足以让您入门。