c语言 - 为什么 Linux 不能防止生成无限数量的进程和崩溃?



使用下面这段非常简单的代码,我的系统(Ubuntu Linux 14.04)甚至没有让我的鼠标响应就崩溃了。我不得不用电源键强行退出。我认为Linux是一个稳定的操作系统,可以容忍处理这些基本的程序错误。我错过什么了吗?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
void check(int isOkay){
  if(!isOkay){
    printf("errorn");
    abort();
  }
}
int main(void){
  #define n 1000000
  int array[n];
  sem_t blocker;
  int i;
  while(1){
    if(!fork()){
      for(i = 0; i < n; ++i){
        array[i] = rand();
      }
      check(sem_init(&blocker, 0, 0) == 0);
      check(sem_wait(&blocker) == 0);
    }
  }
  return 0;
}

恭喜你,你已经发现了叉子炸弹。有一些shell一行程序可以用更少的输入来实现同样的功能。

实际上,可以使用ulimit限制用户可以生成的进程数量——参见链接wikipedia文章的底部了解详细信息。

桌面安装的Ubuntu并不完全是一个加固过的服务器。它的设计首先是为了可用性。如果你需要一个不会崩溃的锁定系统,还有更好的选择。

命令ulmit -u显示可以启动的最大进程数。然而,不要在后台启动那么多进程:你的机器会花时间在进程之间切换,而不会有时间去完成实际的工作。

linux完成它的工作来处理你的请求来创建一个进程,它是由用户基于这个限制来实现他的代码。

这里的主要问题是确定最佳限制。许多软件根本不使用fork(),所以您是否将限制设置为像5这样的小值?有些软件可能会在从网络接收请求时创建一个新进程,所以您是否将限制设置为"max"?"网络数据包数"?如果您假设大多数软件没有错误,那么您可能会试图将限制设置得相对较高,以便正确的软件能够正常工作。

另一个问题是调度优先级。在一个设计良好的系统中,像GUI这样的东西应该是"高优先级的",如果它需要CPU时间,它会立即抢占正常/低优先级的工作。如果是这样的话,一个以正常/较低优先级运行的大规模分叉炸弹将不会对系统响应用户的能力产生影响,并且用户将能够毫无问题地杀死分叉炸弹。

遗憾的是,由于各种原因,Linux中的调度器不是这样工作的。它确实支持优先级,但要使用它们,您必须是一个"实时"进程,并且必须以root身份运行(这是一个巨大的安全灾难)。如果没有合理的优先级,Linux假定每个分叉进程都和其他进程一样重要,CPU最终会忙于分叉,没有CPU时间来响应用户。

最新更新