为什么堆溢出“允许”冻结系统?

时间:2016-12-04 20:32:33

标签: c linux memory-management operating-system heap-memory

此代码在命令行中输入一个数字作为输入,并多次调用heapOverflow()函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void heapOverflow()
{
    unsigned *some_array = malloc(50000);
}

int main(int argc, char *argv[])
{
    unsigned num_calls = atoi(argv[1]);

    while (num_calls > 0)
    {
        heapOverflow();
        num_calls--;
    }

    return 0;
}

在Linux Mint 17.1上,以足够大的输入(例如我的情况下为10000000)运行它会冻结系统几分钟,然后bash返回“Killed”,然后系统会保持缓慢几分钟。

为什么操作系统允许进程将内存接管到这种程度?当调度程序和内存管理器明确表示它将请求过多的堆内存时,它是否应该协同工作来终止进程?或者是否存在将所有这些内存提供给一个进程可能有用的情况(即,即使在系统的其余部分或至少X GUI系统被冻结的情况下,该进程是否可以实际执行有用的工作?)

1 个答案:

答案 0 :(得分:1)

  

为什么操作系统允许进程将内存接管到这种程度?

因为它被配置为这样做。

Linux内核支持POSIX.1-2008中标准化的每个进程资源限制等功能。见例如prlimit用于命令行访问这些,getrlimit()/setrlimit()用于C库接口。

在大多数Linux发行版中,这些限制由limits.conf中的可插入验证模块pam_limits设置。

问题是,这些限制是特定于任务的。它们在不同系统之间变化很大,甚至从用户到用户也是如此:有些人不喜欢他们的系统开始寻呼(像OP描述的那样慢下来),而且宁愿过程失败;其他人宁愿等待一段时间,因为他们实际上需要资源匮乏过程的结果。设置限制是系统管理员的责任。

我想可以轻松编写一个程序来检查当前配置(特别是/proc/meminfo),并为单用户台式机/笔记本电脑设置资源限制。但是,你也可以创建一个帮助脚本,比如/usr/local/bin/run-limited

#!/bin/sh
exec prlimit --as=1073741824 --rss=262144 "$@"

因此您可以运行任何地址空间限制为1 GB且常驻设置大小(实际使用的RAM数量)为256k页的程序。