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

How can I list all the child pids before passing them control?

我有一个作业,教授要求父进程在将控制权传递给子进程之前打印每个子进程的进程 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 全部开始 运行 之前获取它们。我基本上是在寻找一种方法来创建我需要的所有子进程,也许让它们在创建后立即休眠,然后在它们继续之前从父进程打印出它们的所有 pid。

您似乎完全没有理解 fork 的要点。这是一个非常特殊的函数 - 它 return 是 0 或 non-negative 整数,或者 -1。分叉后您需要做的第一件事是检查 return 值。

如果它是 non-negative,这意味着您正在 parent 中执行并且您可以继续您的 parent 其他事情。 return 值是刚刚生成的 child 进程的 PID。

如果为-1,则出现错误(非常奇怪的情况),如果为0,则表示您现在正在执行child进程,您应该做点什么else - child 应该做的事情。

任何 fork 的结果未立即用 parent 分支检查的代码 child 进程始终是错误代码。

我真的不想为你完成作业,但我建议你从类似这样的事情开始:

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个描述符。这将使您有机会打印出 pids 或其他内容,然后告诉他们该怎么做。如果您不完全理解这一点,请查看 "pipe" 和 "fork" 的手册页。我希望这足以让您入门。