运行fork()

时间:2019-10-15 02:22:17

标签: c process fork execvp waitpid

我在尝试通过execvp()运行多个命令时遇到问题。为此,我有一个while循环遍历每个命令,将其解析,然后调用一个函数以使用fork + exec。

问题是,我将运行fork + exec,并且在等待exec通过的同时,父级运行并继续进行第二个循环,即。第二个命令。但是据我所知,发生的是上一个循环中的子进程接管了,突然之间,子进程就是当前进程。

如何在子流程中运行流程,但在父流程中保持控制?我在SO上看到的所有示例都是针对父进程的,它等待子进程终止再继续,但是我在此分配中没有选择-我应该让子进程保持运行并在以后检查看看它们是否仍在运行。

这是我思考过程的一些伪代码:

funct forkprocess() {
   //call fork
   //call execvp within child process, let process run and return control to parent
       //if execvp failed, kill child process
   //return child pid
}

int main() {
   while(not end of file containing list of commands) :
      //parse command for execvp call
      //call forkprocess() to run process
      //if childpid is returned, report it and store pid
      //else, report failure
   }
}

我的输出接近以下内容:

\\parent PID is printed
\\any code outside the if-else ladder for fork is printed
\\it jumps back to main and prints any statements there

[jumps to next iteration in loop, ie. the next command]

\\child PID is printed
\\parent PID is printed
\\any code outside the if-else ladder for fork is printed
\\it jumps back to main and prints any statements there
\\child PID is printed

2 个答案:

答案 0 :(得分:0)

您需要确保exec仅在子级而不是父级中被调用。当fork()返回时,它会两次(一次在孩子中,一次在父母中),然后返回以下values

  • 非零(子代的PID)(如果我们在父代中)。我们可以使用该PID来等待孩子使用waitpid终止。
  • 如果我们在孩子中,则为零。
  • 如果分叉失败(在这种情况下,由于无法创建子进程,它在父进程中仅返回一次),则为负数

您可能要考虑使用以下结构:

int pid = fork();
if(pid < 0) {
    perror("fork"); // remember to error check!
} else if (pid == 0) {
    // We are in the child
    // ...
    if(execvp(...) < 0) {
        perror("exec");
    }
} else {
    // We are in the parent; wait for the child to terminate using waitpid if desired.
    waitpid(...);
}

为简单起见,我在此处包括waitpid调用;由于您的分配要求您保持子进程的运行,因此以后可以使用该功能或​​处理SIGCHLD来检查其状态。

答案 1 :(得分:0)

int main(int argc, char ** argv) {
    int status;

    if((waitpid(fork(), &status, 0)) == -1) {
       execvp(...);
       /* print error */
       exit(1);
    }
    return 0;
}

感谢您提出问题,如果将fork直接传递给waitpid,则父级将等待,而子级将执行exec,这将在成功时退出线程或在失败时返回并继续打印错误并退出。 这对于一次执行多个功能确实很有帮助...

int main(int argc, char ** argv) {
    int *status = malloc(sizeof(int) * (argc - 1));
    int i = 0;

    while(((waitpid(fork(), &status[i++], 0)) == -1) || i < argc) {
       execvp(argv[i], &argv[i + 1]);
       /* print error */
       exit(1);
    }
    return 0;
}