歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux 下malloc的探究

Linux 下malloc的探究

日期:2017/3/1 9:42:58   编辑:Linux編程

前幾天看《操作系統:精髓與設計原理》的虛擬存儲系統的時候想到個問題,一個程序是否可以無限制的分配內存空間。今天剛好有點時間,就寫了個小程序試了試。

《操作系統精髓與設計原理(原書第六版)》PDF中文版 下載:http://www.linuxidc.com/Linux/2014-06/103324.htm

程序如下

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

int mian()
{
int *p;
int i=0;
while(1)
{
p=(int *)malloc(sizeof(char)*1024*1024);
i++;
printf("%dM\n",i);
}

}


運行的結果讓我和我的小伙伴都驚呆了 。。。居然能分配100G+。。並且還能繼續分配。。當時就嚇尿了啊。。。

哥這破二手電腦也就只有40G的內存啊。。怎麼能分配這麼多呢?

於是哥又想到了內存洩漏,可能每次內存如果沒有指針去指向它的話可能就直接釋放了。

於是

p=(int *)malloc(sizeof(char)*1024*1024*(i+1));

居然還是和原來一樣!!!看來原來C學C的時候還是學的太淺了啊。。

然後又想到是不是沒有使用那一塊內存,所以gcc直接優化掉了。

於是就在分配內存下面增加了一條語句

memset(p,i,sizeof(char)*1024*1024)

分配語句改成第一次的樣子。

這次總算是正常了。前800M都是很快出來。估計是可以直接用內存的原因(只有1G內存)。

但是後面的就出來很慢了。大概一秒也就刷5到6行的樣子。個人猜測可能是用到了虛擬內存的緣故,不斷的IO操作,讓速度慢了很多。

到1200M在左右的時就基本就不能動了。。所以只好乖乖的等待被內核干掉了。

大概8分鐘左右的樣子,程序出現了Out of memory的字樣。提示說結束進程或者犧牲掉孩子(英語不好。。)。

然後下面兩排提示殺掉了進程,行尾顯示:total -vm 2728124KB anon -rss 869736KB file -rss 88KB

最後排就顯示個killed.

於是問題又來了。這些數字是個什麼意思呢。。

total 意思估計就是總的大小吧。已經分配了的磁盤+內存空間大小。

anon的意思就沒這麼容易看出來了。不過從之前的觀察來看,似乎是內存使用的大小。

file 這個如果是文件的長度,似乎不太對頭啊。估計是內核分配給程序的初始空間大小吧。

查了下swap的大小,2015.99M=2064373.76k。用total-anon差不多180000+K的樣子,還沒有把磁盤交換區占滿,估計是還有其他程序也占用了吧。

弄了半天,malloc分配的空間,好像除了物理限制,似乎沒有給設定一個最大分配的值啊。果斷用man來查查看。

man這個東西還是好啊,又學了很多東西。

第一段:

malloc這個函數通常是在程序內存堆中用sbrk這個函數來分配空間。並且是有限制的,在MMAP_THRESHOLD中設置了上限,默認大小是128K,可以用mallopt()來調整。

超過128K之後則用mmap來分配內存空間,並且不受RLIMIT_DATA(通過getrlimit設置)的影響。那RLIMIT_DATA是個什麼呢?下面是百度上的解釋。

一個進程的數據段最大字節長度。數據段中初始化數據、非初始化數據以及堆的總和。當調用函數brk動態改變一個進程的數據段大小時,若失敗,errno值將被設置為ENOMEM。

真是越看越覺得自己了解的少啊。。為什麼要設置這個RLIMIT_DATA呢。。為何mmap可以不受RLIMIT_DATA影響呢。。以後再慢慢學吧。

第二段:

一般glibc庫中是默認會自動設置錯誤信息的。如果自己寫一個當然就不一定了(廢話。。)。另外,還有一個MALLOC_CHECK_可以用來設置檢查錯誤的強度。

貌似設置成0就可以無限分配內存了?估計電腦會直接掛掉吧。。。

第三段(malloc有BUG!):

如果沒有內存分配的時候,malloc會返回一個non-NULL(估計是個NULL),並不保證這塊內存可以使用。然後系統會了解到內存沒有了,還會通過OOM來亂殺進程。

但是剛才看OOM的資料時說,OOM會給每個進程打分,分最高的會被殺掉。這麼看來。。這個BUG是不是就沒有了。。

不過在多進程的情況下,可能在剛換到另一進程的時候,這個進程又分配了一點空間和之前那個准備殺掉的進程一樣。這樣就可能殺掉其他無關進程了。

當然這樣的情況還與kill設置有關,最後還是得看OOM怎麼實現的。

最後,sbrk和brk還有mmap也是內存分配的函數,只是沒有malloc用的那麼方便。mmap直接映射到內存,效率估計比操作數據段的brk和sbrk要快得多吧。

Copyright © Linux教程網 All Rights Reserved