现在的位置: 首页 > 综合 > 正文

linux内存管理初步探索

2013年03月10日 ⁄ 综合 ⁄ 共 3772字 ⁄ 字号 评论关闭

首先理解一个概念,linux基本上使用的都是32位的整数和32位的指针来指向内存的,32位的指针可寻址的最大地址空间是4G字节。系统直接使用的是32位指针来寻址,而不像8086那样使用地址偏移量来寻址,了解win32内存结构的人应该清楚,这种寻址被成为32位的内存模型(flat 32-bit memory model)。这四个G的内存是一个虚拟的地址空间,也就是说无论你真实的物理内存具体是多少,你的程序可访问的空间都是4G!下面看以下的代码。

我用的是Fedora10.0,装载VMware虚拟机当中,内存分配大小是512M。

 

很快程序就跑完了,最后一行的结果是:

Now allocate 3056 Megabytes

也就是说我现在的内存分配了3G,我的实际物理内存只有512M!这个就验证了我刚才所说的虚拟4G的内存地址空间,虚拟的内存地址空间只有在被访问的时候才会映射到真正的物理内存上。那为什么不是分配了4个G?嘿嘿,你操作系统难道不需要内存了?

然后我们把程序的注释稍微改动一下下

 

我们这次以kb为单位对内存进行分配,可以明显的感觉到当分配的内存超过我的物理内存512M的时候我的linux操作系统分配内存的速度明显慢了,因为这个时候他在使用我的交换空间(swap space),你用一个模拟终端登录上去使用free -m命令查看你的交换空间大小就知道了。这是因为我的物理内存不够用了,当前应用程序已经耗尽了我的物理空间,所以只能启用交换空间。linux中的内存实现的是一个“请求分页的虚拟内存系统”。linux的内存是以页为单位的每页的大小是4k,也就是说内存的映射必须是以4k为单位的。而我以k的单位分配的话,他所有的虚拟内存都需要物理内存对应,就算启用了我的交换空间(我的设置为一个G),总物理内存可以看成1.5G,所以最后的运行结果:

 

Now allocated 1444 Megabytes

Killed

而以MB为单位分配内存,一兆的空间只会映射到一个4k的物理空间上,所以很快就能在物理内存上分配,根本不需要启用交换空间,速度很快。感兴趣的同学可以尝试采用不同单位比如4k, 8k, 80k ...你会看到不同的结果,分析就能知道得到这种结果的原因。

 

 

简单说了一下linux的内存分配,那linux的进程空间内所有的段的分布是如何呢?众所周知,进程有5个不同的数据段,分别为栈段、堆段、BSS段、数据段、代码段。那他们都具体是表示什么的?

栈:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

 

BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。

 

数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。

代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。

 

 

 

那他们在内存中的分配是如何呢?用一个小程序演示一下就可以了,代码如下:

 

我的电脑下的运行结果如下:

 

 

below are address of types of process's memory

 

 

Stack segment Addree(Address of stack_var0):0xbfa86c38

 

Heap segment Address(Address of heap):0x928f008

 

BSS segment Address(Address of bss_var):0x80498b8

 

Data segment Address(Address of data_var0):0x80498ac

 

Code segment Address(Address of main function):0x8048454

 

done...

 

 

这个就很清楚明白,这个程序很好的证明了5个不同数据段在内存中的排列。需要说明的是,栈和堆的增长方向是反的。栈向下增长(趋向内存地址更小的地方),堆向上增长(趋向内存地址更大的地方)。如下图

上述部分东西摘自linux程序设计和网上的一些资料,首次对linux的内存做了简单了解。

抱歉!评论已关闭.