免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 821 | 回复: 0
打印 上一主题 下一主题

[内核入门] 物理页面周转(分配/释放、换出/换入) [复制链接]

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-09-19 19:01 |只看该作者 |倒序浏览
本帖最后由 _nosay 于 2016-09-20 10:52 编辑

本篇文章是对《Linux内核源代码情景分析》2.6~2.9节(共65页)非常粗略的总结,更深入了解需要看书和代码


    某个虚拟页面,为其分配一个物理页面,并建立映射关系后(建立映射关系的过程中,可能还需要分配页表),硬件在访问这个虚拟页面中的虚拟地址时,才不会出错。所以说物理页面是非常宝贵的资源,每个进程拥有自己的4G虚拟空间,但物理内存只有一份(≤4G),由所有进程共享,因此设计一种合理的物理页面周转策略,就尤为重要!比如提供释放机制,保证进程在确定不再使用某块内存时,有渠道可以将它还给系统;比如长时间没有使用,但又没释放的物理页面,在内存紧缺时,可以先将它的内容拷贝到磁盘(相应虚拟地址的映射方向也要改为指向这块磁盘,当硬件将来访问这块虚拟地址时,重新找一块物理内存与其建立映射,并从磁盘恢复原来的内容),将其挪出来急用;等等。



  • 内核空间映射
    通过之前的文章,很新的新手朋友,可能仍然对内核空间心存焦虑,不能完全明白内核空间到底是什么?
    首先要明确,用户空间、内核空间只是对虚拟空间的划分(用户:0~3G,内核:3~4G),用户进程调用malloc()等内存分配函数,是不可能返回3~4G范围的虚拟地址的(否则就是内核有bug)。
    其次要明确,用户态与内核态切换,跟进程切换是两回事(即使进程切换必须进入内核完成,《Linux内核源代码情景分析》第四章)。之前提到过,“切换”的本质,就是硬件状态的改变,而这两种切换,改变的硬件不一样,比如用户态与内核态切换,改变了段寄存器的RPL值,进程切换时,改变了CR3寄存器值。
    那么,由于用户进程通过系统调用等方式进入内核空间,CR3寄存器值不变(只会在进程切换时改变),就是说3~4G范围虚拟地址依据的映射关系不变,都是该进程的映射表。那么很显然,每个进程目录表(也正好一页)尾部1/4的表项,不会像用户空间空间内存释放那样--撤消映射关系时,如果撤消的是页表中最后一个表项,将该页表也释放。任何进程尾部1/4的目录表项,都指向256个相同的页表(可以把这些目录表项理解为“指针”),这256个页表在内核启动时分配,并且再也不会释放。这样,各个进程用相同的内核空间虚拟地址,访问到的最终物理页面也会一样,并且某个进程新建或撤消了256个页表中的某些表项,其它进程进入内核态时也能“发现”(“公共空间”)。
    同时,很自然能理解为什么内核空间的映射规则简单了,因为任何进程的同一内核虚拟地址,本来就应该映射到同一物理页面,而简单的映射规则就已经可以保证这一点。


    顺便再想一下,为什么不像固定的256个PT一样,也搞个固定的PGD,硬件设计上保证用户态切换到内核态时,CR3切换到该PGD位置?
    这样,进程进入内核后,就没办法再访问自己的用户空间。


  • 分配/释放
    ① 分配/释放虚拟页面(虚拟地址也要当作资源来管理,否则malloc(2G),free(2G),malloc(2G),free(2G)..即使物理页面分配到了,也会认为“代号”不够而分配失败)
    ② 分配/释放物理页面
    ③ 建立/撤消虚拟页面与物理页面映射关系


  • 换出/换入
   
    当物理页面紧缺时,内核会根据一些策略挑选一些物理页面(比如分配了,但很长时间没有访问的),将它们的内容复制到交换文件的某个逻辑页(驱动以“块”为单位操作磁盘,1个文件逻辑页一般又映射到4个磁盘块,那么也就是某4个block上),并修改相应页表项的值,表示虚拟页面的内容已经不在物理页面,而是磁盘上。

    ① 虚拟页面<->物理页面,pte结构(pte_t):
   
    高20位分别是PGD下标、PT下标;剩余低12位表示该物理页面的属性,其中最低的P位,表示物理页面是否存在(换出了就相当于“不存在”了),所以只要物理页面没被换出,P位肯定为1。

    ② 虚拟页面<->交换文件逻辑页面,pte结构(swp_entry_t):
   
    type表示映射到第几个交换设备(系统中最多可以有128个交换设备,每个设备由一个swap_info_struct结构表示);offset表示对应的页面内容,映射到该设备的第几个逻辑页面(0下标逻辑页面永远不用于映射,所以只要有映射,该位段的值不可能为0)。

    总之,P=1,pte对应于①说明的结构,虚拟页面肯定映射到一个物理页面;P=0,pte对应于②说明的结构,当offset非0时,虚拟页面肯定映射到一个交换文件的逻辑页面,当offset也为0时,相应的虚拟页面还没有映射(未分配/已释放),访问时就可能出现段错误或得到扩展。
    另外,硬件只认①说明的结构,P=0时,硬件就会认为有错误发生了,从页要经历一次中断过程,最终调用do_page_fault()函数。

    换入是换出的逆过程:do_page_fault()函数,会判断错误的原因,如果是由于物理页面被换出了(pte != 0),就会分配一个物理页面,并从交换文件拷贝内容,并将映射关系再改为虚拟页面到物理页面的映射。


  • 换出/换入策略
    由于换出过程需要写磁盘操作(比较慢),如果在内存真正出现紧缺时才换出,系统就会显得很“卡顿”,所以Linux内核的策略是“未雨绸缪”,在空闲的时候为换出操作做一些准备,这样,在真正执行换出操作时,就可以少做一些事情。
    具体怎么准备呢?
    方案①:将物理页面内容复制到磁盘,映射方向也改向磁盘
    这种方案确实为分配操作带来了实惠,因为它总是在腾出可用的物理页面,但对于之前使用这个物理页面的进程来说,这样做是在“添乱”,当进程再次想访问这些物理页面时,发现已经不在了,要重新分配物理页面,并从磁盘把内容读回来。
    方案②:将物理页面内容复制到磁盘,但不是马上就将映射方向也改变,而是在对应page结构中,用一些信息表示,这个页面的内容已经复制到磁盘,当需要换出这个页面时,只需要修改映射就OK了,这样一来,真正的换出就很快了,而浪费时间的操作是系统空闲时完成的(反正闲着也是闲着,顶多浪费点电
   
    有了大致思路,再去理解换出/换入过程的细节,就只是时间问题了。同时也能感受到,很多结构体、变量关系也不是一下子就想出来的,最终的设计是经过长期的实践得到的,比如page结构、不活跃脏链表、管理区中的不活跃干净链表等。


  • 用户空间内存页面性质
    ① 程序指令、全局/静态变量、起始堆栈,内核在创建/销毁该进程时分配/释放;
    ② 程序中调用malloc()/free()、mmap()/unmmap()等,在进程执行过程中分配/释放。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP