【问题标题】:What happens to the resources that aren't cleaned up when you use _exit in UNIX?在 UNIX 中使用 _exit 时未清理的资源会怎样?
【发布时间】:2011-08-31 20:05:38
【问题描述】:

我了解到,当您希望终止 UNIX 中的进程时,您可以调用 exit_exit,并且退出释放资源(当我们从 main 返回时使用的样式),其中 _exit 立即终止而没有清理。

用_exit关闭程序对运行环境有什么影响,为什么要使用它?

【问题讨论】:

  • 我将把真正的答案留给更有知识的人,但如果程序不知道如何继续,它通常会调用 _exit。例如,如果您同时抛出两个异常。一般来说,无论出于何种原因,堆栈展开都是一个坏主意。

标签: c++ c unix


【解决方案1】:

除非您安装了atexit 处理程序,否则使用_exitexit 退出时释放的资源没有区别。命名的共享内存对象、SysV IPC 资源、文件系统中的文件等不会在任何一种退出类型中被破坏;分配给进程的内存(实际上是它的整个虚拟内存空间)、文件描述符等都将被销毁。有关详细信息,请阅读 POSIX 中的文档:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html

http://pubs.opengroup.org/onlinepubs/9699919799/functions/exit.html

通常唯一重要的区别是,如果您使用_exit,stdio FILE 对象可能不会被刷新(一些写入可能会丢失)。

【讨论】:

  • 您忽略了 C/C++ 在调用 main 之前自动安装 atexit 处理程序。
  • 文件流(描述符)也是资源。 exit() 会清理这些,而 _exit() 不会。
  • @Tux-D:我的回答提到 FILE 对象不会被_exit 刷新。然而,无论它们是否被刷新,资源都会被释放。底层文件描述符由_exit 关闭,当进程的整个虚拟内存空间被丢弃时,用户空间缓冲区将不复存在。
  • @David:C 和 C++ 都不会“自动安装 atexit 处理程序”。两种语言都指定了在程序终止时发生的一些事情——对于 C,只是刷新/关闭打开的 FILE 对象,对于 C++,也运行静态析构函数。如果使用_exit,这些操作将不会发生。
  • @R..:这是您引用的 POSIX 标准,而 POSIX 忽略了 C++。下面是 Linux 是如何实现这一点的:refspecs.freestandards.org/LSB_3.2.0/LSB-Core-generic/…。 Itanium ABI 将全局数据的析构函数调用放在与atexit 注册的函数相同的列表中。
【解决方案2】:

来自手册页:

exit

exit()函数首先调用所有注册的函数 atexit(3C),按照注册的相反顺序, 除了在之前的任何一个函数之后调用 已经被调用的注册函数 注册时间。

_exit:

_Exit() 和 _exit() 函数在功能上是 相等的。他们不调用注册的函数 atexit(),不要调用任何已注册的信号处理程序,并执行 不刷新打开的流。

换句话说,exit_exit 如果操作系统这样做,仍然会进行资源(例如文件句柄和分配的堆内存)回收,但不会调用用户定义的东西,例如静态析构函数,并且文件在_exit 的情况下不会被刷新。

【讨论】:

    【解决方案3】:

    您的程序会自动配备一些默认的atexit() 处理程序。致电exit()

    • 仍然打开的文件和管道的流将被刷新和关闭。
    • 全局数据将被销毁。

    致电_exit()

    • 仍然打开的文件和管道的流不会被刷新。您很可能会丢失输出文件中的数据。
    • 不会破坏全局数据。

    在这两种情况下,

    • 您分配的所有内存都会恢复。
    • 您没有收获的已退出子进程仍将在进程表中(但是,僵尸似乎不是很久以前的大问题。)
    • 仍在运行的子进程成为孤儿,并在init 进程中被采用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-29
      • 1970-01-01
      相关资源
      最近更新 更多