红联Linux门户
Linux帮助

linux 下虚拟内存的影响

发布时间:2008-02-27 20:52:45来源:红联作者:uzrcgunr
也许你很少面临这一情况,但是一旦如此,你一定知道出什么错了:可用内存不足或者说内存用尽(OOM)。结果非常典型:你不能再分配内存,内核会杀掉一个任务(一般是正在运行那个)。一般半随着大量的交换读写,你可以从屏幕和磁盘动向看出来。

这个问题下面隐含着别的问题:你需要分配多少内存?操作系统给你分配了多少?OOM的基本原因很简单,你申请的内存多于系统可用量。我得说是虚拟内存,因为交换分区也包括在内。

了解OOM

开始了解OOM,首先试试这段会分配大量内存的代码:

引用:
#include
#include
#define MEGABYTE 1024*1024
int main(int argc, char *argv[])
{
void *myblock = NULL;
int count = 0;
while (1)
{
myblock = (void *) malloc(MEGABYTE);
if (!myblock) break;
printf(”Currently allocating %d MBn”, ++count);
}
exit(0);
}


编译一下,运行它之后等一会。系统早晚会OOM。然后试试下面这段,分配大量内存并用1写入:

引用:
#include
#include
#define MEGABYTE 1024*1024
int main(int argc, char *argv[])
{
void *myblock = NULL;
int count = 0;
while(1)
{
myblock = (void *) malloc(MEGABYTE);
if (!myblock) break;
memset(myblock,1, MEGABYTE);
printf(”Currently allocating %d MBn”,++count);
}
exit(0);
}


发现差别了么?A比B分配了更多内存。而且B被杀掉的更早一些。两个程序都因为没有可用内存而退出。更准确的说,A因为失败的malloc()而优雅的退出了,B是被OOM杀手干掉了。

首先观察分配的内存块数。假设你使用256M内存,888M交换分区(我的情况),B结束时:

Currently allocating 1081 MB
而A结束时:

Currently allocating 3056 MB

A怎么弄来的另外1975M?我骗人?没有!如果你仔细看,你会发现B用1填满得到的内存,而A几乎不拿他们干什么。Linux允许推迟的页分配,换句话说,只当你真的要用的时候才开始分配动作,比如写入数据时。所以,除非写入数据,否则你可以一直要更多内存。术语称之为乐观的内存分配。

查看/proc//status来确认信息。

引用:
$ cat /proc//status
VmPeak: 3141876 kB
VmSize: 3141876 kB
VmLck: 0 kB
VmHWM: 12556 kB
VmRSS: 12556 kB
VmData: 3140564 kB
VmStk: 88 kB
VmExe: 4 kB
VmLib: 1204 kB
VmPTE: 3072 kB


这是在B被杀之前的记录:

引用:
$ cat /proc//status
VmPeak: 1072512 kB
VmSize: 1072512 kB
VmLck: 0 kB
VmHWM: 234636 kB
VmRSS: 204692 kB
VmData: 1071200 kB
VmStk: 88 kB
VmExe: 4 kB
VmLib: 1204 kB
VmPTE: 1064 kB


VmRSS需要再详细点解释。RSS是Resident Set Size,也就是当前进程在内存中分配的块。也注意,在B到OOM之前已经用掉了几乎全部交换分区,而A根本没用。很明显malloc()除了保留内存之外什么也没做。

另外一个问题是:既然没有写页,为什么有3056M这个上限?这暴露出另外一个限制。在32位系统上,内存地址有4GB。其中0-3GB是用户使用,3-4GB为内核空间。

注意:有内核补丁可以实现全部分配4GB给用户空间,需要一些上下文切换的开销。OOM的结论:

VM中没有可用页。
没有足够的用户地址空间。
以上两者。

另外,在linux 环境下,用malloc分配的内存空间会比可见的free memory要大(见下例,malloc size =0x7d000000 > MemFree: 1762136 kB),也是因为交换空间swap存在造成的。而嵌入式单板上没有swap区,就不会出现这个情况。

引用:
[wind@fw-csvr mpc8313]$ cat /proc/meminfo

MemTotal: 2074844 kB

MemFree: 1762136 kB

Buffers: 21764 kB

Cached: 229040 kB

SwapCached: 23016 kB

Active: 236684 kB

Inactive: 38376 kB


[wind@fw-csvr mpc8313]$ ./mpc8313_mem_mini

Now doing DDR SDRAM test, please wait............

diagSDRAMSub[88] : malloc size =0x7d000000, addr = 0x3a5db008!

ddrMemDiag[53]: test size = 2000MB! time = 118s


swap交换区的知识参见:《揭开Linux系统Swap交换区之谜》
文章评论

共有 0 条评论