退出的Syscall实现()

我写了一个简单的C程序,只调用exit()函数,但是strace说二进制文件实际上是调用exit_group,exit()是一个exit_group()包装器吗? 这两个function是否相同? 如果是这样,为什么编译器会选择exit_group()而不是exit()?

Linux和glibc手册页记录了所有这些(请参阅NOTES部分中的“C库/内核差异”)。

  • _exit(2) :在glibc 2.3及更高版本中,这个包装函数实际调用Linux sys_exit_group系统调用来退出所有线程。 在glibc2.3之前,它是sys_exit的一个包装器, sys_exit退出当前线程。
  • sys_exit :仅终止当前线程,使其他线程继续运行。 AFAIK,现代glibc没有这个Linux系统调用的包装函数,因为它通常没用。
  • exit_group(2)sys_exit_group glibc包装器,退出所有线程。
  • exit(3) :ISO C89函数,它刷新缓冲区然后退出整个过程。 (它总是使用exit_group()因为检查进程是否是单线程并决定使用sys_exitsys_exit_group没有任何好处。 正如@Matteo所指出的 ,最近的ISO C或POSIX标准是线程感知的,其中一个或两个可能需要这种行为。

    但显然exit(3)本身不是线程安全的(在C库清理部分),所以我猜不要一次从多个线程调用它。

只有exit() ,而不是_exit()exit_group() ,刷新stdout ,导致新手asm程序中的“ printf不打印任何东西”问题,如果写入管道(使stdout全缓冲而不是行缓冲) ,或者如果您忘记格式字符串中的\n 。 例如, 如何_exit(0)(由syscall退出)阻止我接收任何标准内容? 。 如果你使用任何缓冲的I / O函数,或at_exit ,或类似的东西,通常最好直接调用libc exit(3)函数而不是系统调用。 但是当然你可以在sys_exit_group之前调用fflush


它当然不是选择任何东西的编译器 ,它是libc。 当您包含头文件并写入read(fd, buf, 123)exit(1) ,C编译器只会看到普通的函数调用。

一些C库(例如musl ,但不是glibc)可以使用内联asm将syscall指令内联到二进制文件中,但是头文件仍然是C库的一部分,而不是编译器。