Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2712590
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2013-05-24 10:26:45

Linux内存分配有其特殊性,理解其分配机制,将有助于调试程序,特别是和内存泄露相关的问题分析,本文件试图以示例的方式简单的讲解一下Linux内存分配机制,希望对你的工作有所帮助。

先粘贴出示例将使用的源代码,为了方便讲解,为每行加上行号,如下:
1) #include
2) #include
3) #include
4)
5) int main()
6) {
7)    const size_t st = 1024*1024;  // 1M大小
8)    const size_t ss = 1*1024*1024*1000;  // 1G大小
9)    char* p = new char[ss];
10)    for (size_t i=0; i
11)        getchar();  // 停顿一下,是为了方便观察内存的变化,下同
12)        memset(p, 0, st);
13)        p += st;
14)    }
15)    char* p2 = new char[ss];
16)    getchar();
17)    memset(p2, 0, ss);
18)    getchar();
19)    return 0;
20) }

要想比较透彻地了解Linux内存分配机制,还需要明白top或free命令中的几个属性:
l         VIRT:进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
l         SWAP:进程使用的虚拟内存中,被换出的大小,单位kb
l         RES:进程使用的、未被换出的物理内存大小(即当前实际占用的物理内存),单位kb。RES=CODE+DATA
另外,free命令还包括“-/+ buffers/cache”两个属性,前者(-buffers/cache)表示实际被占用的物理内存数,而后者(+buffers/cache)表示可以被应用程序使用的内存总数。

这几个属性和程序中的内存分配(malloc/new)之间有什么关系了?
malloc分配的内存反映的是VIRT的变化,所以如果VIRT值一直在不停的往上增涨,则说明程序中存在内存泄露,否则表示程序不存在泄露。
而通过大家只关注了RES值,当RES值不断的往上涨时,就认识程序存在内存泄露,其实这是不正确的,只要VIRT值没有增涨,那么即使RES值在增涨,也不代表内存泄露,只有VIRT值在不停地增涨,才能表示程序存在内存泄露,这点将通过上面的示例程序来说明。
在现代操作系统中,进程可使用的均是虚拟的地址空间,程序并不直接和物理内存打交道,对一个32位程序,理论上其可用内存最大为4G,这通常是比物理内存 大。只有当malloc出来的进程被实在的使用后,才会表现在RES上,RES表示的是实实在在的有多少物理内存被应用程序占用了。

当示例程序第一次运行到第11行时,使用ps aux命令查看该进程的内存使用量时,可以发现其VIRT对应的值为1G多,而VSS值通常远远小于它,然后按Enter回车键,让它执行完第12行,这 个时候再使用ps aux查看它的内存占用情况,可以发现VIRT值保持不变,但VSS值增加了1M大小。
当程序运行到第16行时,我们可以发现,其VIRT值也增大了。

另外,Linux内存分配采用了贪婪的算法,它总是优先从“从未动用过的内存(对应top命令中的free值)”里取出一块内存供程序使用,只有当从这里 取不到需要的内存时,才会根据淘汰算法,从cache里面拿出一块内存,这也可以通过非常简单的实验来展现这个现象,写一个非常简单的程序,程序运行时分 配一块大于free值而小于cached值的内存,运行结束之后,会发现free值变大了,而cached变小了,内存就这样被强制从cached中解放 出来了,但在实际中不建议这样操作,因为cached的目的就是为了提高性能。
阅读(1738) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~