linux有什么措施可以防止叉子炸弹吗?


12
#include <unistd.h>
int main(int argc, char* argv[]) {
  while(1)
  {
    fork();
  } 
}

我在Linux上运行此程序,终端上没有任何输出,操作系统似乎死了。linux对这种可能耗尽内存的程序有什么保护措施吗?


2
我怀疑的影响将会少了很多,如果你没有按照不好的建议许多发行版给创建一个较大的交换分区...
R.,GitHub上停止帮助ICE

1
“达到65k后不创建任何新流程”是否算作对策?;)
Bobby

Answers:


18

这就是所谓的叉子炸弹

linux对这种可能耗尽内存的程序有什么保护措施吗?

并不是的。每个派生都有其自己的虚拟地址空间和内存使用情况的新进程。因此,每个副本相对较小。最终,您将用完系统上的所有物理+交换内存,而内存不足(OOM)杀手将开始杀死单个进程。但是前叉炸弹仍将以同样快的速度(即使不是更快)创建进程。

首先防止这种情况发生的一种方法是,使用来限制用户进程的数量ulimit -u(假设您使用的是Bash;其他Shell将具有等效功能)。


2
需要注意的一件事ulimit是bash特有的。其他外壳可能具有相同的内置命令,但名称可能不同。
周杰伦

@杰伊:公平点。我已经在回答中指出了,谢谢!
奥利弗·查尔斯沃思

1
限制每个用户的内存/文件描述符就足够了。限制每个用户的内存始终是一个好主意。当进程被杀死(oom)时,看门狗应发送通知,以便BOFH可以引导“流氓”用户使用系统中的所有相关进程

我相信您也可以通过登录参数设置一些限制
p_l 2012年

10

是的,尽管默认情况下可能未启用它。的setrlimit系统调用定义系统限制-包括每个用户的进程数。

让我们首先在内核API中对其进行研究(因为您提到了“ linux”):您可以将手册页用于setrlimit,这将告诉您执行类似的操作

#include <sys/resource.h>
...

struct rlimit  r;

rnew.r_cur = 40;
rnew.r_max = 50;
setrlimit(RLIMIT_NPROC,&r);

这会将每个用户的最大进程数(RLIMIT_NPROC)设置为40(软限制)和50(硬限制)。

现在,从外壳程序开始,如果您使用bash,则可以使用ulimit内置命令:

ulimit -u
29089

您可以通过将限制作为参数传递来设置限制:

ulimit -u 100

ulimit --help 将显示您可以设置其他几个限制(一个可能是用户使用的文件描述符的最大数量)。


7

这取决于您是否要在用户级别或系统级别使用它。在用户级别,ulimit(或其他外壳程序的相应命令)将是最简单的解决方案。

但是,在系统级别,有一些机制可以防止恶意用户(或只是不使用ulimit)阻止系统。Linux cgroups机制可以按组限制资源。您可以(通过机制pam_systemd)强制用户会话属于特定组。例如,对于CPU调度程序,这还有其他好处。


1
+1:cgroup确实很新,大多数人对此还不了解。在哪里可以了解更多?
肯·布鲁姆

1
@KenBloom:1.通过浏览/sys/fs/cgroup/2.在Google中搜索3.通过浏览make menuconfig4.通过研究/usr/src/linux/Documentation/cgroups5.通过阅读systemd文档。抱歉,我不能提供更多帮助,但我只使用了那些资源。我在桌面上使用cgroups来控制资源。
Maciej Piechotka 2012年

6

使用ulimit -u从bash shell中设置的“最大用户进程”的限制。

在C shell中,使用limit命令。

如果您需要系统调用来执行此操作,请使用setrlimit调用set RLIMIT_NPROC


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.