从开发者的角度学习Linux内存管理
内存管理一向是所有操作系统书籍不惜笔墨重点讨论的内容,无论市面上或是网上都充斥着大量涉及内存管理的教材和资料.因此,我们这里所要写的Linux内存管理采取避重就轻的策略,从理论层面就不去班门弄斧,贻笑大方了.我们最想做的和可能做到的是从开发者的角度谈谈对内存管理的理解,最终目的是把我们在内核开发中使用内存的经验和对Linux内存管理的认识与大家共享. 进程如何使用内存? 毫无疑问,所有进程(执行的程序)都占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内存是事先静态分配和统一回收的,而有些却是按需要动态分配和回收的. 对任何一个普通进程来讲,它都会涉及到5种不同的数据段.稍有编程知识的朋友都能想到这几个数据段中包含有“程序代码段”、“程序数据段”、“程序堆栈段”等.不错,这几种数据段都在其中,但除了以上几种数据段之外,进程还另外包含两种数据段.下面我们来简单归纳一下进程对应的内存空间中所包含的5种不同的数据区. 代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像.代码段需要防止在运行时被非法修改,只准许读取操作,而不允许写入(修改)操作——它是不可写的. 数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量. BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零. 堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减.当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减) 栈:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量).除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中.栈的先进先出特点,栈特别方便用来保存/恢复调用现场.从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区. 进程如何组织这些区域? 上述几种内存区域中数据段、BSS和堆通常是被连续存储的——内存位置上是连续的,而代码段和栈往往会被独立存放.有趣的是,堆和栈两个区域关系很“暧昧”,他们一个向下“长”(i386体系结构中栈向下、堆向上),一个向上“长”,相对而生.但你不必担心他们会碰头,他们之间间隔很大(到底大到多少,你可以从下面的例子程序计算一下),绝少有机会能碰到一起. 下图简要描述了进程内存区域的分布: “事实胜于雄辩”,我们用一个小例子(原形取自《User-Level Memory Management》)来展示上面所讲的各种内存区的差别与位置. #include #include #include int bss_var; int data_var0=1; int main(int argc,char **argv) { printf("below are addresses of types of process''s mem\n"); printf("Text location:\n"); printf("\tAddress of main(Code Segment):%p\n",main); printf("____________________________\n"); int stack_var0=2; printf("Stack Location:\n"); printf("\tInitial end of stack:%p\n",&stack_var0); int stack_var1=3; printf("\tnew end of stack:%p\n",&stack_var1); printf("____________________________\n"); printf("Data Loc |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |