Linux中子进程的退出状态
众所周知,fork() 系统调用用于创建一个新进程,该进程成为调用者进程的子进程。
退出时,子进程会留下退出状态,该状态应返回给父进程。所以,当孩子完成时,它就变成了僵尸。
每当子进程退出或停止时,父进程都会收到一个 SIGCHLD 信号。
父进程可以使用系统调用 wait() 或 waitpid() 以及宏 WIFEXITED 和 WEXITSTATUS 来了解其停止子进程的状态。
(*)wait() 系统调用:它暂停调用进程的执行,直到其子进程之一终止。
wait() 系统调用的语法:
pid_t wait(int *status);
(*)waitpid() 系统调用:它暂停调用进程的执行,直到 pid 参数指定的子进程改变状态。
waitpid() 系统调用的语法:
pid_t waitpid(pid_t pid, int *status, int options)
注意:默认情况下,waitpid() 仅等待终止的子进程,但可以通过选项参数(如 WIFEXITED、WEXITSTATUS 等)修改此行为。
pid 的值可以是:
- 小于 -1 :表示等待进程组 ID 等于 pid 绝对值的任何子进程。
- 等于 -1 :意味着等待任何子进程。
- 等于 0 :表示等待进程组 ID 等于调用进程组 ID 的任何子进程。
- 大于 0 :表示等待进程 ID 等于 pid 值的子进程。
WIFEXITED 和 WEXITSTATUS 是两个可用于了解子进程退出状态的选项。
WIFEXITED(status) : 如果子进程正常终止,则返回 true。
WEXITSTATUS(status) :返回孩子的退出状态。仅当 WIFEXITED 返回 true 时才应使用此宏。
下面是一个 C 实现,其中 child 使用 execl()函数,但指定给 execl() 的路径未定义。
让我们看看 parent 获取的 child 的退出状态值是多少。
C
// C code to find the exit status of child process
#include
#include
#include
#include
#include
// Driver code
int main(void)
{
pid_t pid = fork();
if ( pid == 0 )
{
/* The pathname of the file passed to execl()
is not defined */
execl("/bin/sh", "bin/sh", "-c", "./nopath", "NULL");
}
int status;
waitpid(pid, &status, 0);
if ( WIFEXITED(status) )
{
int exit_status = WEXITSTATUS(status);
printf("Exit status of the child was %d\n",
exit_status);
}
return 0;
}
输出:
注意:由于 fork() 被禁用,以上代码可能不适用于在线编译器。
这里的退出状态是 127,这表明路径有问题或有拼写错误。
下面列出了一些退出状态代码以获取额外信息:
- 1 : 杂项错误,例如“除以零”等不允许的操作。
- 2 : 缺少关键字或命令,或权限问题。
- 126:权限问题或命令不是可执行文件
- 128 : 无效的退出参数。
注意:C 标准没有定义返回码的含义。返回码的使用规则因平台而异。