从开发者的角度学习Linux内存管理
应的页表(init_mm.pgd),用户进程各自有不同的页表.
第三、每个进程的用户空间都是完全独立、互不相干的.不信的话,你可以把上面的程序同时运行10次(当然为了同时运行,让它们在返回前一同睡眠100秒吧),你会看到10个进程占用的线性地址一模一样. 进程内存管理 进程内存管理的对象是进程线性地址空间上的内存镜像,这些内存镜像其实就是进程使用的虚拟内存区域(memory region).进程虚拟空间是个32或64位的“平坦”(独立的连续区间)地址空间(空间的具体大小取决于体系结构).要统一管理这么大的平坦空间可绝非易事,为了方便管理,虚拟空间被划分为许多大小可变的(但是4096的倍数)内存区域,这些区域在进程线性地址中像停车位一样有序排列.这些区域的划分原则是“将访问属性一致的地址空间存放在一起”,所谓访问属性在这里无非指的是“可读、可写、可执行等”. 如果你要查看某个进程占用的内存区域,可以使用命令cat /proc//maps获得(pid是进程号,你可以运行上面我们给出的例子——./example &;pid便会打印到屏幕),你可以发现很多类似于下面的数字信息. 程序example使用了动态库,除了example本身使用的的内存区域外,还会包含那些动态库使用的内存区域(区域顺序是:代码段、数据段、bss段). 我们下面只抽出和example有关的信息,除了前两行代表的代码段和数据段外,一行是进程使用的栈空间. 08048000-08049000 r-xp 00000000 03:03 439029 /home/mm/src/example 08049000-0804a000 rw-p 00000000 03:03 439029 /home/mm/src/example bfffe000 - c0000000 rwxp ffff000 00:00 0每行数据格式如下: (内存区域)开始-结束 访问权限 偏移 主设备号:次设备号 i节点 文件. 注意,你一定会发现进程空间只包含三个内存区域,似乎没有上面所提到的堆、bss等,其实并非如此,程序内存段和进程地址空间中的内存区域是种模糊对应,也就是说,堆、bss、数据段(初始化过的)都在进程空间中由数据段内存区域表示. 在Linux内核中对应进程内存区域的数据结构是: vm_area_struct, 内核将每个内存区域作为一个单独的内存对象管理,相应的操作也都一致.采用面向对象方法使VMA结构体可以代表多种类型的内存区域--比如内存映射文件或进程的用户空间栈等,对这些区域的操作也都不尽相同. vm_area_strcut结构比较复杂,关于它的详细结构请参阅相关资料.我们这里只对它的组织方法做一点补充说明.vm_area_struct是描述进程地址空间的基本管理单元,对于一个进程来说往往需要多个内存区域来描述它的虚拟空间,如何关联这些不同的内存区域呢?大家可能都会想到使用链表,的确vm_area_struct结构确实是以链表形式链接,不过为了方便查找,内核又以红黑树(以前的内核使用平衡树)的形式组织内存区域,以便降低搜索耗时.并存的两种组织形式,并非冗余:链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空间中定位特定内存区域的时候.内核为了内存区域上的各种不同操作都能获得高性能,同时使用了这两种数据结构. 下图反映了进程地址空间的管理模型: 进程的地址空间对应的描述结构是“内存描述符结构”,它表示进程的全部地址空间,——包含了和进程地址空间有关的全部信息,其中当然包含进程的内存区域. |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |