malloc和free的一些理解

1.虚拟内存,在32位平台下,一个进程一般拥有3g的虚拟内存地址,这些虚拟内存地址将包含,代码区,数据区,堆区,栈区等,事实上一个进程在初始化的时候,虚拟内存地址需要通过一个地址映射表才能转换为实际的物理地址,一个进程在初始化的时候操作系统不会为其分配很多的物理地址,当程序中有动态分配内存的请求时,操作系统会调整分配给进程的物理地址。

2.malloc的原理:malloc是c的一个库函数,不同平台下有不同的实现,基本思想是,先看看当前进程的堆空间有没有够用的内存,有的话就返回,否则向操作系统要新的内存,此时会调用sbrk,brk,mmap等函数来实现,其中sbrk是对brk的封装也是属于c的库函数,而在linux下brk和mmap都有对应的内核方法,由于linux下内存是按页分配的,(一般是4k一页),那么申请到的内存也是页面大小的整数倍,此时进程的虚拟内存地址会发生变化,通常是堆空间的上限提升,(堆是从低到高增长),但在访问新的内存地址之前,进程的占用的内存不会增大。

1 int main() {
2     int *p = malloc(sizeof(int)  * 8);
3     //memset(p,0,sizeof(int)*8);      
4     return 0;
5 }

如果memset被注释掉,对于进程来说改变的就只有虚拟内存的大小(建立虚拟内存和物理内存的映射关系),若是取消掉注释,由于此时新申请的内存并不在进程内存空间中,memset访问到该内存的时候会出现缺页中断,os会将新的内存以换页的方式调度进进程的内存空间。

3.free的原理,对于用户的内存分配请求,实际上分配的内存会大于用户的申请内存,这是因为返回给用户的内存地址的前面有一个头结构,对于free只需要让指针回退,然后设置一些标记位即可。

4.内存管理实际上就是实现自己的malloc和free,因为brk,mmap是系统调用,会有较大的性能消耗(内核态用户态的转换),那么对于已经分配到的进程内存,就需要一个较好的策略来管理,比如free的时候将前后的空闲块合并成一个大的空闲块来减小碎片化问题,还有考虑并发的问题。

posted @ 2013-12-30 10:35  xpray  阅读(439)  评论(0编辑  收藏  举报