编辑
2023-10-25
linux
00
请注意,本文编写于 563 天前,最后修改于 563 天前,其中某些信息可能已经过时。

今天执行strace的时候发现,不管哪个进程最后都会调用exit_group,就打算总结一下进程退出相关的系统调用。 ,查阅资料后发现有以下。

image.png 1. exit()

  • exit() 是标准 C 库中的函数,用于终止当前进程。
  • 函数原型:void exit(int status);
  • 调用 exit() 函数将终止当前进程,并将退出状态 status 返回给父进程。
  • exit() 函数将执行一系列清理操作,包括关闭文件描述符、刷新缓冲区以及执行通过 atexit() 注册的终止处理程序。
  • 可以使用 EXIT_SUCCESSEXIT_FAILURE 宏来表示进程的成功或失败状态。

2. _exit()

  • _exit() 是一个系统调用,用于立即终止当前进程,不执行清理操作。
  • 函数原型:void _exit(int status);
  • 调用 _exit() 函数将立即终止当前进程,并将退出状态 status 返回给父进程。
  • _exit() 不会执行清理操作,包括不会关闭文件描述符、不会刷新缓冲区,也不会执行终止处理程序。

3. atexit()

  • atexit() 函数用于注册在进程终止时自动执行的终止处理程序。
  • 函数原型:int atexit(void (*function)(void));
  • 通过调用 atexit() 函数并传递一个函数指针,可以注册一个终止处理程序。
  • 注册的终止处理程序将在进程正常终止时被调用,执行一些清理操作。
  • 可以多次调用 atexit() 来注册多个终止处理程序,它们将按照注册的相反顺序执行。

4. exit_group()

  • exit_group() 是 Linux 特定的系统调用,用于终止整个进程组中的所有进程,包括当前进程。
  • 函数原型:void exit_group(int status);
  • 调用 exit_group() 将立即终止当前进程组中的所有进程,包括当前进程。
  • exit_group() 不执行清理操作,也不返回到调用进程,因为它会终止整个进程组。

这些 API 提供了不同的方式来控制进程的退出和清理操作。

接下来演示一下网上找到的的示例程序

  1. 示例程序:使用 exit() 终止进程
c
#include <stdio.h> #include <stdlib.h> int main() { printf("This is the main process.\n"); // 调用 exit() 终止当前进程 exit(EXIT_SUCCESS); // 下面的代码不会被执行 printf("This line will not be printed.\n"); return 0; }

当程序执行到 exit() 时,当前进程将被终止。因此,printf() 函数后面的代码将不会被执行。

  1. 示例程序:使用 _exit() 终止进程
c
#include <stdio.h> #include <unistd.h> int main() { printf("This is the main process.\n"); // 调用 _exit() 终止当前进程 _exit(EXIT_SUCCESS); // 下面的代码不会被执行 printf("This line will not be printed.\n"); return 0; }

当程序执行到 _exit() 时,当前进程将被立即终止。与 exit() 不同,_exit() 不执行清理操作,直接退出。

  1. 示例程序:使用 atexit() 注册终止处理程序
c
#include <stdio.h> #include <stdlib.h> void cleanup() { printf("Executing cleanup...\n"); // 执行一些清理操作 } int main() { printf("This is the main process.\n"); // 注册终止处理程序 atexit(cleanup); // 调用 exit() 终止当前进程 exit(EXIT_SUCCESS); // 下面的代码不会被执行 printf("This line will not be printed.\n"); return 0; }

cleanup() 函数作为终止处理程序被注册。当进程正常终止时,注册的终止处理程序将被调用,执行一些清理操作。

  1. 示例程序:使用 exit_group() 终止进程组中的所有进程
c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { printf("This is the main process. PID: %d\n", getpid()); // 创建一个子进程 pid_t child_pid = fork(); if (child_pid == 0) { // 子进程 printf("This is the child process. PID: %d\n", getpid()); // 子进程调用 exit_group() 终止整个进程组 exit_group(EXIT_SUCCESS); } else if (child_pid > 0) { // 父进程 printf("This is the parent process. PID: %d\n", getpid()); // 等待子进程终止 int status; wait(&status); if (WIFEXITED(status)) { printf("Child process terminated with exit status: %d\n", WEXITSTATUS(status)); } } else { // fork() 失败 perror("fork"); exit(EXIT_FAILURE); } // 下面的代码不会被执行 printf("This line will not be printed.\n"); return 0; }

在这个示例中,主进程创建了一个子进程,并等待子进程终止。子进程调用了 exit_group() 终止整个进程组。当子进程终止后,父进程会检查子进程的退出状态并打印出来。

进程组是进程的集合,通常是由父进程创建,父进程创建子进程并将其加入到自己这个进程组,进程组的PGID就等于父进程自己的PID,子进程初始的PGID也等于父进程的PID,除非子进程创建会话成为另一个会话的领导者,子进程的PGID会变成自己的PID,还有通过setpgid手动加入到其他进程组。

所以,exit_group会杀死和这个程序有关的所有进程。s

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!