linux C语言 exit()函数

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux C语言 exit()函数相关的知识,希望对你有一定的参考价值。

文章目录

man 2 exit

_EXIT(2)                                          Linux Programmer's Manual                                         _EXIT(2)

NAME
       _exit, _Exit - terminate the calling process	//终止调用进程

SYNOPSIS
       #include <unistd.h>

       void _exit(int status);

       #include <stdlib.h>

       void _Exit(int status);

   Feature Test Macro Requirements for glibc(glibc 的功能测试宏要求) (see feature_test_macros(7)):

       _Exit():
           _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;
           or cc -std=c99

DESCRIPTION
       The  function  _exit()  terminates  the  calling  process  "immediately".  Any open file descriptors belonging to the
       process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent  a
       SIGCHLD signal.
       //_exit() 函数“立即”终止调用进程。 属于该进程的任何打开的文件描述符都将关闭; 
       //进程的任何子进程都由进程 1 init 继承,并且进程的父进程会收到一个 SIGCHLD 信号。

       The  value  status  is returned to the parent process as the process's exit status, and can be collected using one of
       the wait(2) family of calls.

       The function _Exit() is equivalent to _exit().

RETURN VALUE
       These functions do not return.

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.  The function _Exit() was introduced by C99.

NOTES
       For a discussion on the effects of an exit, the transmission of exit status, zombie processes, signals sent,  and  so
       on, see exit(3).

       The  function _exit() is like exit(3), but does not call any functions registered with atexit(3) or on_exit(3).  Open
       stdio(3) streams are not flushed.  On the other hand, _exit() does close open file descriptors, and this may cause an
       unknown  delay,  waiting for pending output to finish.  If the delay is undesired, it may be useful to call functions
       like tcflush(3) before calling _exit().  Whether any pending I/O is canceled, and which pending I/O may  be  canceled
       upon _exit(), is implementation-dependent.

   C library/kernel differences
       In  glibc  up  to  version  2.3, the _exit() wrapper function invoked the kernel system call of the same name.  Since
       glibc 2.3, the wrapper function invokes exit_group(2), in order to terminate all of the threads in a process.

SEE ALSO
       execve(2), exit_group(2), fork(2), kill(2), wait(2), wait4(2), waitpid(2), atexit(3), exit(3), on_exit(3), termios(3)

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.  A description of the  project,  information  about
       reporting bugs, and the latest version of this page, can be found at http://www.kernel.org/doc/man-pages/.

Linux                                                    2015-07-23                                                 _EXIT(2)
 Manual page exit(2) line 24/58 (END) (press h for help or q to quit)

发现搞错了,应该看 man 3 exit

EXIT(3)                                                              Linux Programmer's Manual                                                             EXIT(3)

NAME
       exit - cause normal process termination	//导致正常进程终止

SYNOPSIS
       #include <stdlib.h>

       void exit(int status);

DESCRIPTION
       The exit() function causes normal process termination and the value of status & 0377 is returned to the parent (see wait(2)).
       //exit() 函数会导致进程正常终止,并将 status & 0377 的值返回给父进程(参见 wait(2))。

       All  functions registered with atexit(3) and on_exit(3) are called, in the reverse order of their registration.  (It is possible for one of these functions
       to use atexit(3) or on_exit(3) to register an additional function to be executed during exit processing; the new registration is added to the front of  the
       list of functions that remain to be called.)  If one of these functions does not return (e.g., it calls _exit(2), or kills itself with a signal), then none
       of the remaining functions is called, and further exit processing (in particular, flushing of stdio(3) streams) is abandoned.  If a function has been  reg‐
       istered multiple times using atexit(3) or on_exit(3), then it is called as many times as it was registered.
       //使用 atexit(3) 和 on_exit(3) 注册的所有函数都会按照注册的相反顺序被调用。 (这些函数之一可以使用 atexit(3) 或 on_exit(3) 来注册要在退出处理期间执行的附加函数;新注册将添加到仍有待调用的函数列表的前面 .) 如果其中一个函数没有返回(例如,它调用 _exit(2),或用信号杀死自己),则不会调用其余函数,并进一步退出处理(特别是刷新 stdio(3 ) 流) 被放弃。 如果一个函数已经使用 atexit(3) 或 on_exit(3) 注册了多次,那么它被调用的次数与注册的次数一样多。

       All open stdio(3) streams are flushed and closed.  Files created by tmpfile(3) are removed.
       //所有打开的 stdio(3) 流都被刷新和关闭。 由 tmpfile(3) 创建的文件被删除。

       The  C  standard  specifies  two constants, EXIT_SUCCESS and EXIT_FAILURE, that may be passed to exit() to indicate successful or unsuccessful termination,
       respectively.
       //C 标准指定了两个常量,EXIT_SUCCESS 和 EXIT_FAILURE,可以分别传递给 exit() 以指示成功或不成功终止。
       

RETURN VALUE
       The exit() function does not return.
       //exit() 函数不返回。

ATTRIBUTES
       For an explanation of the terms used in this section, see attributes(7).
       //有关本节中使用的术语的解释,请参见属性 (7)。

       ┌──────────┬───────────────┬─────────────────────┐
       │Interface │ Attribute     │ Value               │
       ├──────────┼───────────────┼─────────────────────┤
       │exit()    │ Thread safety │ MT-Unsafe race:exit │
       └──────────┴───────────────┴─────────────────────┘
       The exit() function uses a global variable that is not protected, so it is not thread-safe.
       //exit() 函数使用不受保护的全局变量,因此它不是线程安全的。

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.

NOTES
       It is undefined what happens if one of the functions registered using atexit(3) and on_exit(3) calls either exit() or longjmp(3).   Note  that  a  call  to
       execve(2) removes registrations created using atexit(3) and on_exit(3).
       //如果使用 atexit(3) 和 on_exit(3) 注册的函数之一调用 exit() 或 longjmp(3) 会发生什么,这是未定义的。 
       //请注意,对 execve(2) 的调用会删除使用 atexit(3) 和 on_exit(3) 创建的注册。

       The  use  of  EXIT_SUCCESS and EXIT_FAILURE is slightly more portable (to non-UNIX environments) than the use of 0 and some nonzero value like 1 or -1.  In
       particular, VMS uses a different convention.
       //使用 EXIT_SUCCESS 和 EXIT_FAILURE 比使用 0 和一些非零值(如 1 或 -1)更便于移植(对于非 UNIX 环境)。 
       //特别是,VMS 使用不同的约定。

       BSD has attempted to standardize exit codes; see the file <sysexits.h>.
       //BSD 试图标准化退出代码; 请参阅文件 <sysexits.h>。

       After exit(), the exit status must be transmitted to the parent process.  There are three cases.  If the parent  has  set  SA_NOCLDWAIT,  or  has  set  the
       SIGCHLD handler to SIG_IGN, the status is discarded.  If the parent was waiting on the child, it is notified of the exit status.  In both cases the exiting
       process dies immediately.  If the parent has not indicated that it is not interested in the exit status, but is not waiting, the exiting process turns into
       a "zombie" process (which is nothing but a container for the single byte representing the exit status) so that the parent can learn the exit status when it
       later calls one of the wait(2) functions.
       //在 exit() 之后,必须将退出状态传递给父进程。 
       //有三种情况。 如果父级已设置 SA_NOCLDWAIT,或已将 SIGCHLD 处理程序设置为 SIG_IGN,则丢弃该状态。 
       //如果父母正在 wait 孩子,则会通知退出状态。 
       //在这两种情况下,退出进程都会立即终止。 
       //如果父进程没有表示它对退出状态不感兴趣,但没有等待,退出进程将变成一个“僵尸”进程(它只不过是代表退出状态的单个字节的容器),因此 parent 可以在稍后调用 wait(2) 函数之一时了解退出状态。

       If the implementation supports the SIGCHLD signal, this signal is sent to the parent.  If the parent has  set  SA_NOCLDWAIT,  it  is  undefined  whether  a
       SIGCHLD signal is sent.
       //如果实现支持 SIGCHLD 信号,则此信号将发送给父级。 
       //如果父级设置了 SA_NOCLDWAIT,则未定义是否发送 SIGCHLD 信号。

       If  the  process  is  a session leader and its controlling terminal is the controlling terminal of the session, then each process in the foreground process
       group of this controlling terminal is sent a SIGHUP signal, and the terminal is disassociated from this session, allowing it to be acquired by a  new  con‐
       trolling process.
       //如果进程是会话领导者,并且它的控制终端是会话的控制终端,那么这个控制终端的前台进程组中的每个进程都会被发送一个 SIGHUP 信号,并且该终端与这个会话解除关联,允许它被一个新的控制过程获得。

       If  the exit of the process causes a process group to become orphaned, and if any member of the newly orphaned process group is stopped, then a SIGHUP sig‐
       nal followed by a SIGCONT signal will be sent to each process in this process group.  See setpgid(2) for an explanation of orphaned process groups.
       //如果进程的退出导致进程组成为孤立的,并且如果新孤立的进程组的任何成员停止,则将向该进程组中的每个进程发送一个 SIGHUP 信号和一个 SIGCONT 信号。 
       //有关孤立进程组的说明,请参阅 setpgid(2)。

SEE ALSO
       _exit(2), setpgid(2), wait(2), atexit(3), on_exit(3), tmpfile(3)

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the  latest  version
       of this page, can be found at http://www.kernel.org/doc/man-pages/.

Linux                                                                       2015-08-08                                                                     EXIT(3)
 Manual page exit(3) line 32/73 (END) (press h for help or q to quit)

不是很明白。。。而且exit(0)和exit(1)的区别也没讲。。。

解释一下关于上面文档中提到的exit()函数的线程不安全性(thread safety: MT-unsafe race)

我理解是这样的:这段是说明exit()的特性,特性之一是该函数/调用是否具有线程安全性(安全性,特性的一种,可能安全也可能不安全),也就是说此线程安全性(thread safety)是属性特征,并非说这个exit是线程安全的。
而后面的value则具体说了exit()线程安全性特征的最终结果:MT-unsafe race。就是它是线程不安全的,存在竞争,具体来说,后执行exit的线程会覆盖先执行exit退出后返给调用者的数据,此处应该是errno之类的东西吧,也就是说明中的function uses a global variable that is not protected。
说人(白)话,大概是说exit()线程不安全,由于exit会把一些返回参数放到全局变量里面(至少errno如此),后执行的exit会竞争(更改)先执行exit设置的参数,导致这个参数的具体结果是最后执行的exit的结果,而前面的exit的结果被覆盖(竞争掉)了。
例如,你的程序里起了两个thread,然后一段时间后都退出。在父程序打印errno。那么errno的结果是两个线程共用的,无法区分errno具体是哪个线程执行exit()退出后的结果。
参考文章:线程安全Thread safety和MT-Unsafe是什么意思? - harry4112的回答 - 知乎

意思说exit()函数在某个线程中调用,程序不会结束?有时间要测测才行。。。

以上是关于linux C语言 exit()函数的主要内容,如果未能解决你的问题,请参考以下文章

C语言 exit (0)是啥意思

Linux C _exit函数与exit函数的联系与区别

C语言中的exit函数

c语言exit和return的区别

C语言中exit函数的使用

C语言异常处理和exit()怎样使用?