2016-12-04 44 views
0

這段代碼使用了一些在命令行輸入和調用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」返回之前凍結系統幾分鐘,然後系統在幾分鐘內保持緩慢。

爲什麼OS允許一個進程接管內存達到這樣的程度?調度程序和內存管理器不應該一起工作來清除一個進程,當它明確表示它會請求太多的堆內存時?或者是否存在這樣的情況:將所有這些內存給予一個進程可能是有用的(即,即使系統的其餘部分或至少X GUI系統被凍結,該進程實際上是否可以做有用的工作?)

+1

'malloc'不成功時返回'NULL'。請檢查,這是至關重要的。 –

+2

Linux內核允許內存過度提交(以便允許程序請求比可用內存更多的內存,並且分配成功,但當內存不可用時代碼崩潰)。在您最喜愛的搜索引擎上搜索「Linux OOM Killer」(內存不足殺手)。你的代碼並不真正使用它正在分配的內存;需要很長時間才能用完,因爲您必須耗盡指針的空間,而不是內存本身。如果你在分配它之後清零內存(也許使用'calloc()'),你會更快崩潰,並且對系統的影響更小。 –

+0

當流程實際需要大量內存時,您認爲應該發生什麼?無論如何它應該被殺害? – immibis

回答

1

爲什麼OS允許一個進程接管內存到這樣的程度?

因爲它被配置爲這樣。

除了其他功能外,Linux內核還支持在POSIX.1-2008中標準化的每進程資源限制;見例如prlimit用於命令行訪問這些,而getrlimit()/setrlimit()用於C庫接口。

在大多數Linux發行版中,這些限制是由可插入身份驗證模塊pam_limits在limits.conf中設置的。

問題是,這些限制是非常特定於任務的。它們從系統到系統甚至從用戶到用戶都有很大差異:有些人不喜歡他們的系統開始分頁(像OP描述的那樣放慢速度),寧願進程失敗;其他人則更願意等待一段時間,因爲他們實際上需要從資源匱乏的過程中獲得結果。設置限制是系統管理員的責任。

我想你可以很容易地編寫一個程序來檢查當前的配置(特別是,/proc/meminfo),並設置單用戶臺式機/筆記本電腦的資源限制。但是,你也可以同樣創建一個腳本,說/usr/local/bin/run-limited

#!/bin/sh 
exec prlimit --as=1073741824 --rss=262144 "[email protected]" 

,您可以與地址空間中運行任何你的程序的限制爲1塊GB和駐留集大小(實際使用的內存量)256K頁面。