【问题标题】:How can I list all the child pids before passing them control?如何在传递控制权之前列出所有子 pid?
【发布时间】:2019-06-16 10:32:54
【问题描述】:

我有一个任务,教授要求父进程在将控制权传递给子进程之前打印每个子进程的进程 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后,需要检查当前进程是父进程还是子进程。并相应地工作。在这里,您跨越了孩子们拥有自己孩子的整棵树。
  • 您分叉了 5 次以上。在第一次分叉之后,父母和孩子都继续for 循环。父母分叉 5 次,第一个孩子分叉 4 次,第二个孩子分叉 3 次,以此类推。您忘记了子进程运行所有相同的代码,因此它继续父进程启动的for 循环。
  • 不要使用printf 打印错误消息。使用perrorfprintf 并显式写入stderr。
  • 另见Synchronizing N sibling processes after fork() 在这种情况下,你会让孩子都等待父母让他们运行,父母会在让他们运行之前写出所有的孩子PID。跨度>

标签: c multithreading process fork wait


【解决方案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 或其他内容,然后告诉他们该做什么。如果您不完全理解这一点,请查看“pipe”和“fork”的手册页。我希望这足以让你开始。

【讨论】:

  • 谢谢!我会尝试使用它!
【解决方案2】:

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

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

如果是-1,有一个错误(非常奇怪的情况),如果是0,这意味着你现在正在一个子进程中执行,你应该做一些别的事情——孩子应该做的事情做。

如果fork 的结果未立即使用分支检查父子进程的任何代码,则始终是错误代码。

【讨论】:

    猜你喜欢
    • 2020-02-19
    • 2021-02-07
    • 2012-08-23
    • 2013-09-22
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多