Linux内存管理
不过为了方便查找,内核又以红黑树(以前的内核使用平衡树)的形式组织内存区域,以便降低搜索耗时.并存的两种组织形式,并非冗余:链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空间中定位特定内存区域的时候.内核为了内存区域上的各种不同操作都能获得高性能,同时使用了这两种数据结构. 进程的地址空间对应的描述结构是“内存描述符结构”,它表示进程的全部地址空间,——包含了和进程地址空间有关的全部信息,其中当然包含进程的内存区域. 进程内存的分配与回收 创建进程fork()、程序载入execve()、映射文件mmap()、动态内存分配malloc()/brk()等进程相关操作都需要分配内存给进程.不过这时进程申请和获得的还不是实际内存,而是虚拟内存,准确的说是“内存区域”.进程对内存区域的分配最终都会归结到do_mmap()函数上来(brk调用被单独以系统调用实现,不用do_mmap()), 内核使用do_mmap()函数创建一个新的线性地址区间.但是说该函数创建了一个新VMA并不非常准确,如果创建的地址区间和一个已经存在的地址区间相邻,并且它们具有相同的访问权限的话,那么两个区间将合并为一个.如果不能合并,那么就确实需要创建一个新的VMA了.但无论哪种情况, do_mmap()函数都会将一个地址区间加入到进程的地址空间中--无论是扩展已存在的内存区域还是创建一个新的区域.
同样,释放一个内存区域应使用函数do_ummap(),它会销毁对应的内存区域. 如何由虚变实! 从上面已经看到进程所能直接操作的地址都为虚拟地址.当进程需要内存时,从内核获得的仅仅是虚拟的内存区域,而不是实际的物理地址,进程并没有获得物理内存(物理页面——页的概念请大家参考硬件基础一章),获得的仅仅是对一个新的线性地址区间的使用权.实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请求页机制”产生“缺页”异常,从而进入分配实际页面的例程. 该异常是虚拟内存机制赖以存在的基本保证——它会告诉内核去真正为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在地映射到了系统的物理内存上.(当然,如果页被换出到磁盘,也会产生缺页异常,不过这时不用再建立页表了) 这种请求页机制把页面的分配推迟到不能再推迟为止,并不急于把所有的事情都一次做完(这种思想有点像设计模式中的代理模式(proxy)).之能这么做是利用了内存访问的“局部性原理”,请求页带来的好处是节约了空闲内存,提高了系统的吞吐率.要想更清楚地了解请求页机制,可以看看《深入理解linux内核》一书. map_driver.c,它是以模块形式加载的虚拟字符驱动程序.该驱动负责将一定长的内核虚拟地址(vmalloc分配的)映射到设备文件上.其中主要的函数有——vaddress_to_kaddress()负责对vmalloc分配的地址进行页表解析,以找到对应的内核物理映射地址(kmalloc分配的地址);map_nopage()负责在进程访问一个当前并不存在的VMA页时,寻找该地址对应的物理页,并返回该页的指针. test.c 它利用上述驱动模块对应的设备文件在用户空间读取读取内核内存.结果可以看到内核虚拟地址的内容(ok!),被显示在了屏幕上. 执行步骤 编译map_driver.c为map_driver.o模块,具体参数见Makefile 加载模块 :insmod map_driver.o 生成对应的设备文件 1在/proc/devices下找到map_driver对应的设备命和设备号:grep mapdrv /proc/devices 2建立设备文件mknod mapfile c 254 0(在我的系统里设备号为254) 利用maptest读取mapfile文件,将取自内核的信息打印到屏幕上. |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |