资源描述:
《Linux011-Mem-YuanYi .pdf》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库。
1、Linux0.11下的内存管理作者:袁镱robertyi@163.comQQ:30131195愿借此结交广大linux爱好者1如何在保护模式下实现对物理内存的管理保护模式在硬件上为实现虚拟存储创造了条件,但是内存的管理还是要由软件来做。操作系统作为资源的管理者,当然要对内存的管理就要由他来做了。在386保护模式下,对任何一个物理地址的访问都要通过页目录表和页表的映射机制来间接访问,而程序提供的任何地址信息都会被当成线性地址进行映射,这就使得地址提供者不知道他所提供的线性地址最后被映射到了哪个具体的物理地址单元。这样的措施使得用
2、户程序不能随意地操作物理内存,提高了系统的安全性,但是也给操作系统管理物理内存造成了障碍。而操作系统必须要了解物理内存的使用情况才谈得上管理。要能够在保护模式下感知物理内存,也就是说要能够避开保护模式下线性地址的影响,直接对物理内存进行操作。如何避开呢?正如前面所说:在保护模式下对任何一个物理地址的访问都要通过对线性地址的映射来实现。不可能绕过这个映射机制,那只有让他对内核失效。如果让内核使用的线性地址和物理地址重合,比如:当内核使用0x00001000这个线性地址时访问到的就是物理内存中的0x00001000单元。问题不就解
3、决了吗!linux0.11中采用的正是这种方法。在进入保护模式之前,要初始化页目录表和页表,以供在切换到保护模式之后使用,要实现内核线性地址和物理地址的重合,必须要在这个时候在页目录表和页表上做文章。在看代码之前首先说明几点:由于linus当时编写程序时使用的机器只有16M的内存,所以程序中也只处理了16M物理内存的情况,而且只考虑了4G线性空间的情况。一个页表可以寻址4M的物理空间,所以只需要4个页表,一个页目录表可以寻址4G的线性空间,所以只需要1个页目录表。程序将页目录表放在物理地址_pg_dir=0x0000处,4个页
4、表分别放在pg0=0x1000,pg1=0x2000,pg2=0x3000,pg3=0x4000处下面是最核心的几行代码:在linux/boot/head.s中首先对5页内存清零198setup_paging:199movl$1024*5,%ecx/*5pages-pg_dir+4pagetables*/#设置填充次数ecx=1024*5200xorl%eax,%eax#设置填充到内存单元中的数eax=0201xorl%edi,%edi/*pg_dirisat0x000*/#设置填充的起始地址0,也是页目录表的起始位置202c
5、ld;rep;stosl下面填写页目录表的页目录项对于4个页目录项,将属性设置为用户可读写,存在于物理内存,所以页目录项的低12位是000000000111B以第一个页目录项为例,$pg0+7=0x00001007表示第一个页表的物理地址是0x00001007&0xfffff000=0x00001000;权限是0x00001007&0x00000fff=0x00000007203movl$pg0+7,_pg_dir/*setpresentbit/userr/w*/204movl$pg1+7,_pg_dir+4/*-------
6、--""---------*/205movl$pg2+7,_pg_dir+8/*---------""---------*/206movl$pg3+7,_pg_dir+12/*---------""---------*/接着便是对页表的设置:4个页表×1024个页表项×每个页表项寻址4K物理空间:4*1024*4*1024=16M每个页表项的内容是:当前项所映射的物理内存地址+该页的权限其中该页的属性仍然是用户可读写,存在于物理内存,即0x00000007具体的操作是从16M物理空间的最后一个页面开始逆序填写页表项:最后一个页
7、面的起始物理地址是0x0xfff000,加上权限位便是0xfff007,以后每减0x1000(一个页面的大小)便是下一个要填写的页表项的内容。207movl$pg3+4092,%edi#edi指向第四个页表的最后一项4096-4。208movl$0xfff007,%eax/*16Mb-4096+7(r/wuser,p)*/#把第四个页表的最后一项的内容放进eax209std#置方向位,edi值以4字节的速度递减。2101:stosl/*fillpagesbackwards-moreefficient:-)*/211subl$0
8、x1000,%eax#每填写好一项,物理地址值减0x1000。212jge1b#如果eax小于0则说明全填写好了。#使页目录表基址寄存器cr3指向页目录表。213xorl%eax,%eax/*pg_dirisat0x0000*/令eax=0x00000000(页目录表基址)2