📜  Linux中子进程的退出状态

📅  最后修改于: 2022-05-13 01:57:30.358000             🧑  作者: Mango

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. 小于 -1 :表示等待进程组 ID 等于 pid 绝对值的任何子进程。
  2. 等于 -1 :意味着等待任何子进程。
  3. 等于 0 :表示等待进程组 ID 等于调用进程组 ID 的任何子进程。
  4. 大于 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 标准没有定义返回码的含义。返回码的使用规则因平台而异。