19

在我的简单自定义 shell 中,我从标准输入读取命令并使用 execvp() 执行它们。在此之前,我创建当前进程的一个分支,并在该子进程中调用 execvp(),之后,我调用 exit(0)。

像这样的东西:

pid = fork();

if(pid == -1) {
    perror("fork");
    exit(1);
}

if(pid == 0) {
    // CHILD PROCESS CODE GOES HERE...
    execvp(pArgs[0], pArgs);
    exit(0);
} else {
    // PARENT PROCESS CODE GOES HERE...
}

现在,使用 execvp() 运行的命令可以返回错误,对吧?我想正确处理这个问题,现在我总是调用 exit(0),这意味着子进程将始终处于“OK”状态。

如何从 execvp() 调用中返回正确的状态并将其放入 exit() 调用中?我是否应该只获取 execvp() 返回的 int 值并将其作为 exit() 参数而不是 0 传递。这是否足够且正确?

4

3 回答 3

18

您需要在父代码中使用waitpid(3)wait(1)等待子退出并获取错误消息。

语法是:

pid_t waitpid(pid_t pid, int *status, int options);

或者

pid_t wait(int *status);

status包含退出状态。查看手册页以了解如何解析它。


请注意,您不能从子进程中执行此操作。一旦您调用execvp子进程就了(出于所有实际目的)并被'd 进程替换。exec你可以到达那里的唯一方法exit(0)是如果execvp它本身失败了,但失败不是因为新程序结束了。这是因为它从一开始就没有跑过。

编辑:子进程并没有真正死掉。PID 和环境保持不变,但整个代码和数据都被exec'd 进程替换。您可以指望返回原始子进程,除非exec失败。

于 2009-05-24T14:26:20.293 回答
3

从你的问题很难弄清楚你在问什么。因此,我将尝试讨论几个相关问题:

  • execvp()要么不返回(成功时),要么返回错误。这意味着您的子代码只需要处理错误情况。您的子代码应按照您的建议捕获execvp()并使用该值的结果。exit()您的子代码永远不应该返回 0,因为唯一的成功意味着execvp工作和进程返回 0(或不返回)。
  • 父母可以从waitpid()有关其退出状态的信息中获取子信息。定义了几个宏来从返回的status参数中提取信息。值得注意的是WIFEXITED,告诉您孩子是否“正常”退出,并将WEXITSTATUS孩子的状态传递给exit(). 有关其他宏,请参见waitpid手册页。
于 2009-05-24T14:48:25.863 回答
3

在父进程中使用wait()或。waitpid()这里的一个例子:当操作系统杀死你的进程时返回代码

此外,当子进程死亡时,SIGCHLD信号会发送到父进程。

于 2009-05-24T16:05:08.047 回答