《番茄花园-第四章内存管理lab2.ppt》由会员分享,可在线阅读,更多相关《番茄花园-第四章内存管理lab2.ppt(28页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、番茄花园-第四章内存管理lab2 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望提纲提纲n n页面管理n n页表管理页面管理页面管理n n页面管理链表的结构页面管理链表的结构n n现在我们来讨论用于页面管理的双向链表结构。首先,我们来看一下构现在我们来讨论用于页面管理的双向链表结构。首先,我们来看一下构成这个链表的结点的情况。该结点的结构是在成这个链表的结点的情况。该结点的结构是在memlayout.hmemlayout.h中规定的:中规定的:n ntypedef
2、 LIST_ENTRY(Page)Page_LIST_entry_t;typedef LIST_ENTRY(Page)Page_LIST_entry_t;n nstruct Page struct Page n nPage_LIST_entry_t pp_link;Page_LIST_entry_t pp_link;/*free list link*/*free list link*/n n/pp_ref is the count of pointers(usually in page table entries)/pp_ref is the count of pointers(usually
3、 in page table entries)n n/to this page,for pages allocated using page_alloc./to this page,for pages allocated using page_alloc.n n/Pages allocated at boot time using pmap.cs/Pages allocated at boot time using pmap.csn n/boot_alloc do not have valid reference count fields./boot_alloc do not have val
4、id reference count fields.n nuint16_t pp_ref;uint16_t pp_ref;n n;n n而而LIST_ENTRYLIST_ENTRY的定义则在的定义则在queue.hqueue.h中:中:n n#define#define LIST_ENTRY(type)LIST_ENTRY(type)n nstruct struct n nstruct type*le_next;struct type*le_next;/*next element*/*next element*/n nstruct type*le_prev;struct type*le_pre
5、v;/*ptr to ptr to this element*/*ptr to ptr to this element*/n n 页面管理(续)页面管理(续)n n通过分析,我们可以写出Page结构:n nstruct Page struct Page n nstruct struct n nstruct Page*le_next;struct Page*le_next;n nstruct Page*le_prev;struct Page*le_prev;n n pp_link;pp_link;n nuint16_t pp_ref;uint16_t pp_ref;n n;页面管理(续)页面管理
6、(续)n n链表头的定义链表头的定义n nmemlayout.hmemlayout.h中的:中的:n nLIST_HEAD(Page_list,Page);LIST_HEAD(Page_list,Page);n n和和queue.hqueue.h中的:中的:n n#define#defineLIST_HEAD(name,type)LIST_HEAD(name,type)n nstruct name struct name n nstruct type*lh_first;struct type*lh_first;/*first element*/*first element*/n n n n通过
7、分析,我们发现通过分析,我们发现Page_listPage_list结构实际上可以写成:结构实际上可以写成:n nstruct Page_liststruct Page_listn nstruct Page*lh_first;struct Page*lh_first;n n;n n它只包含了一个指向它只包含了一个指向PagePage结构的指针结构的指针lh_firstlh_first。同时,。同时,page_free_listpage_free_list这个全局变量实际上就是指向页面管理双向链表的头结构了,注这个全局变量实际上就是指向页面管理双向链表的头结构了,注意,它不是一个意,它不是一个s
8、truct Pagestruct Page类型的指针或空结构!类型的指针或空结构!页面管理(续)页面管理(续)n n系统还定义了一些宏来对这个链表头进行操作:系统还定义了一些宏来对这个链表头进行操作:n n#define#defineLIST_FIRST(head)LIST_FIRST(head)(head)-lh_first)(head)-lh_first)/取得头指针取得头指针n n#define#defineLIST_INIT(head)/LIST_INIT(head)/将链表重置将链表重置n n在在queue.hqueue.h中,还定义了很多用于操纵结点和对该双向链表中,还定义了很多用
9、于操纵结点和对该双向链表进行操作的宏:进行操作的宏:n n#define#defineLIST_NEXT(elm,field)LIST_NEXT(elm,field)(elm)-field.le_next)/(elm)-field.le_next)/该宏返该宏返回回elmelm所的下一个页面管理结点的地址。所的下一个页面管理结点的地址。elmelm应该为一个指向页面应该为一个指向页面管理结点的指针,管理结点的指针,field=pp_linkfield=pp_linkn n#define#defineLIST_INSERT_HEAD(head,elm,field)/LIST_INSERT_HEA
10、D(head,elm,field)/这个宏的功能,这个宏的功能,是将是将elmelm指向的页面管理结点成为整个页面管理双向链表的第一个指向的页面管理结点成为整个页面管理双向链表的第一个元素,在实现上,是要求链表头结构(元素,在实现上,是要求链表头结构(page_free_listpage_free_list)的)的lh_firstlh_first指指针指向该结构。这里需要考虑两种情况,一种是链表以前就是空针指向该结构。这里需要考虑两种情况,一种是链表以前就是空的情况,另一种情况,是链表以前不为空的情况。的情况,另一种情况,是链表以前不为空的情况。页面管理(续)页面管理(续)n n#define
11、#defineLIST_INSERT_BEFORE(listelm,elm,field)LIST_INSERT_BEFORE(listelm,elm,field)n n#define#defineLIST_INSERT_AFTER(listelm,elm,field)LIST_INSERT_AFTER(listelm,elm,field)n n/这两个宏所要做的事情,是把新的结点(这两个宏所要做的事情,是把新的结点(elmelm参数),插入到结参数),插入到结点点listelmlistelm之前或者之后。对于之前或者之后。对于PagePage结构的结构的pp_link.le_nextpp_li
12、nk.le_next指针的使用,指针的使用,应该比较容易理解,需要解释的是应该比较容易理解,需要解释的是pp_link.le_prevpp_link.le_prev的使用。在链表的使用。在链表的结点中,这个域所指向的前一个结点的(的结点中,这个域所指向的前一个结点的((elm)-(elm)-pp_link.le_nextpp_link.le_next)的地址!)的地址!n n#define#defineLIST_REMOVE(elm,field)/LIST_REMOVE(elm,field)/该宏所做的工作是将该宏所做的工作是将elmelm所所指向的结点从页面管理链表中消除。这里要注意指向的结
13、点从页面管理链表中消除。这里要注意pp_link.prevpp_link.prev的用的用法,它只是用来法,它只是用来indexindex前一个结点的前一个结点的le_nextle_next域,从而直接修改里面域,从而直接修改里面的内容,而不能索引整个前面的结点(比方说访问前一个结点的的内容,而不能索引整个前面的结点(比方说访问前一个结点的pp_refpp_ref域的内容),虽然,从链表构造的角度来说,这样设计就足域的内容),虽然,从链表构造的角度来说,这样设计就足够了。够了。n n#define#defineLIST_FOREACH(var,head,field)/LIST_FOREACH(
14、var,head,field)/这个宏实际上写的是这个宏实际上写的是一个一个forfor循环头,它的作用是在该循环中遍历页面管理链表。需要循环头,它的作用是在该循环中遍历页面管理链表。需要注意的是,这个循环是不能用注意的是,这个循环是不能用pp_link.le_prevpp_link.le_prev域来替代的!域来替代的!页面管理(续)页面管理(续)n n页面管理链表结构页面管理链表结构n n注:注意这里实线和虚线的含义注:注意这里实线和虚线的含义页面管理(续)页面管理(续)n n页面管理链表在内存中的存储和放置n nBoot_alloc();Boot_alloc();n nPage_init
15、();Page_init();n ncheck_page_alloc();check_page_alloc();页面管理(续)页面管理(续)n n页面管理的操作n npage_alloc();page_alloc();n npage_free();page_free();页表管理页表管理n n三类地址三类地址n n逻辑地址(逻辑地址(Virtual AddressVirtual Address)n n是指程序在编译连接后,变量名字等的符号地址,在是指程序在编译连接后,变量名字等的符号地址,在JOSJOS系统系统中的内核部分,该地址是以中的内核部分,该地址是以KERNBASEKERNBASE(默
16、认等于(默认等于0 xF00000000 xF0000000,实际上可以根据具体的情况加以修改)开始的。,实际上可以根据具体的情况加以修改)开始的。n n线性地址线性地址(Linear Address)(Linear Address)n n是指经过是指经过x86x86保护模式的段地址变换后的地址,该变换的过程保护模式的段地址变换后的地址,该变换的过程是是 逻辑地址逻辑地址+段首地址段首地址n n物理地址物理地址(Physical Address)(Physical Address)n n是指内存存储单元的编址,如是指内存存储单元的编址,如1GB1GB的内存,它的物理编址是从的内存,它的物理编址
17、是从0 x000000000 x00000000到到0 x400000000 x40000000。页表管理(续)页表管理(续)n n三类地址的关系三类地址的关系页表管理(续)页表管理(续)n n段式地址转换n n过程为程序的逻辑地址段首地址过程为程序的逻辑地址段首地址n n例如段首地址为例如段首地址为0 xf0000000 xf000000时,一个逻辑地址时,一个逻辑地址为为0 xf01000000 xf0100000。经过转换后,得到线性地址。经过转换后,得到线性地址0 x001000000 x00100000。n n分页机制需要经过设置分页机制需要经过设置CR3CR3和和CR0CR0后才打
18、开。后才打开。n n在未打开分页机制的情况下,段式地址转换得在未打开分页机制的情况下,段式地址转换得到的线性地址就是物理地址。到的线性地址就是物理地址。n n在打开分页机制之后,线性地址需要再次经过在打开分页机制之后,线性地址需要再次经过页式地址变换才能得到物理地址。页式地址变换才能得到物理地址。页表管理(续)页表管理(续)n n页式地址转换页式地址转换页表管理(续)页表管理(续)n n对页式地址转换的说明对页式地址转换的说明n n当启用了当启用了x86x86页式内存管理后,当处理器碰到一个线性页式内存管理后,当处理器碰到一个线性地址后,它会把这个地址分成地址后,它会把这个地址分成3 3部分:
19、它们分别是页目部分:它们分别是页目录索引(录索引(DirectoryDirectory)、页表索引()、页表索引(TableTable)和页内偏移)和页内偏移(OffsetOffset),这),这3 3个部分把原本个部分把原本3232位的线性地址分成了位的线性地址分成了1010位、位、1010位和位和1212位的位的3 3个片段。既然页内偏移地址占个片段。既然页内偏移地址占1212位,位,页的大小就自然为页的大小就自然为4KB4KB了。了。n nCode walkCode walkn nInc/mmu.hInc/mmu.h中,定义了宏中,定义了宏PDX(la)PDX(la),用于取得线性地址,
20、用于取得线性地址la la的页目的页目录索引录索引n n定义了定义了PTX(la)PTX(la),用于取得线性地址,用于取得线性地址la la中的页表索引中的页表索引n n定义了定义了PGOFF(la)PGOFF(la),用于取得页内偏移,用于取得页内偏移n n同时注意该头文件中的其他宏定义,如同时注意该头文件中的其他宏定义,如PTE_PPTE_P、PTE_UPTE_U、PTE_WPTE_W,它们用于定义页表项的权限,它们用于定义页表项的权限页表管理(续)页表管理(续)n n页目录(表)项的格式页目录(表)项的格式n n每个页目录或者页表都存储在单独的页面中每个页目录或者页表都存储在单独的页面
21、中n n每个每个4KB4KB的物理页面,实际上它在内部分成了的物理页面,实际上它在内部分成了10241024个个单元(单元(1010位有位有10241024个可能的值),每个单元占个可能的值),每个单元占4 4字节字节(3232位,也就是保护模式下一个位,也就是保护模式下一个uint32_tuint32_t类型所占的内类型所占的内存空间大小),它们称为页目录项(存空间大小),它们称为页目录项(Page Directory Page Directory EntryEntry),这些单元与页表中包含的单元在格式上是),这些单元与页表中包含的单元在格式上是一致的,不同的是页表中的单元称为页表项(一致
22、的,不同的是页表中的单元称为页表项(Page Page Table EntryTable Entry)。)。页表管理(续)页表管理(续)n n页目录(表)项的格式(续)页目录(表)项的格式(续)n n高高2020位存储的是一个地址,但因为只有高位存储的是一个地址,但因为只有高2020位(使用的时候低位会被全部位(使用的时候低位会被全部清零),所以只能寻址清零),所以只能寻址4KB4KB对齐的地址空间(这就是为什么我们在为页目对齐的地址空间(这就是为什么我们在为页目录分配空间时要寻找内核代码后第一个录分配空间时要寻找内核代码后第一个4KB4KB对齐的地址的原因),同时,对齐的地址的原因),同时,
23、由于由于x86x86把所有物理内存分成了把所有物理内存分成了4KB4KB大小的页,每个页的首地址必然是大小的页,每个页的首地址必然是4KB4KB对齐的!所以这个表项中的高对齐的!所以这个表项中的高2020位地址能够定位到内存中任何一个物理页位地址能够定位到内存中任何一个物理页面的首地址。面的首地址。n nP PresentP Present,该位用来判断对应物理页面是否存在,如果存在,该位置,该位用来判断对应物理页面是否存在,如果存在,该位置1 1,否则为,否则为0 0;n nR/W Read/WriteR/W Read/Write,该位用来判断对所指向的物理页面的访问权限,如,该位用来判断对
24、所指向的物理页面的访问权限,如果为果为1 1,表示页面可写,否则,是只读页面;,表示页面可写,否则,是只读页面;n nU/S User/SupervisorU/S User/Supervisor,该位用来定义页面的访问者应该具备的权限。,该位用来定义页面的访问者应该具备的权限。如果为如果为1 1,表示该页面是,表示该页面是UserUser权限的,大家都可以访问,如果为权限的,大家都可以访问,如果为0 0,表示只,表示只能是能是Ring0Ring0中的程序能访问;中的程序能访问;n nD DirtyD Dirty,是否被修改;,是否被修改;n nA AccessedA Accessed,最近是否
25、被访问;,最近是否被访问;n nAVAIL AvailableAVAIL Available,可以被系统程序所使用;,可以被系统程序所使用;n n0 0 保留位,不能使用。保留位,不能使用。n n这些位系统在访问一个页面时就会自动地去判断,如果访问不符合规矩这些位系统在访问一个页面时就会自动地去判断,如果访问不符合规矩(如页面根本就不存在,或者权限不对的情况),系统就会产生异常,让(如页面根本就不存在,或者权限不对的情况),系统就会产生异常,让系统去处理。系统去处理。页表管理(续)页表管理(续)n n页式地址转换的分析页式地址转换的分析n n该机制能够对该机制能够对04GB04GB空间内的任何
26、线性地址进行转换,这时,页空间内的任何线性地址进行转换,这时,页目录的每个页目录项都将指向一个包含目录的每个页目录项都将指向一个包含10241024个页表项的页表(占个页表项的页表(占用一个用一个4KB4KB的物理页面),整个页式转换机制将占用额外的的物理页面),整个页式转换机制将占用额外的1024+1=10251024+1=1025个个4KB4KB的物理页面,也就是大约的物理页面,也就是大约4MB4MB。然而,由于系。然而,由于系统运行过程中可能不会用到这么大的地址空间,所以不会有那么统运行过程中可能不会用到这么大的地址空间,所以不会有那么多页表被创建。多页表被创建。n n为每个用户进程创建
27、一个页目录,并将这个页目录保存到用户进为每个用户进程创建一个页目录,并将这个页目录保存到用户进程的上下文中,当该用户进程被切换过来执行的时候,就将该用程的上下文中,当该用户进程被切换过来执行的时候,就将该用户进程的页目录地址写入户进程的页目录地址写入CR3CR3,并重新启动一次页式内存管理。这,并重新启动一次页式内存管理。这样就能够实现每个用户进程的虚地址空间为样就能够实现每个用户进程的虚地址空间为4GB4GB。当然如果采用。当然如果采用这种方式,势必占用更多的内存用于页式地址变换。这种方式,势必占用更多的内存用于页式地址变换。n n对于老版本的对于老版本的LinuxLinux系统以及我们现在
28、接触的系统以及我们现在接触的JOSJOS系统,为了避免系统,为了避免太大的内存开销(另一个原因是因为还没有虚拟内存的支持),太大的内存开销(另一个原因是因为还没有虚拟内存的支持),在整个系统中只使用一个页目录。这就意味着,整个系统的线性在整个系统中只使用一个页目录。这就意味着,整个系统的线性地址空间只有地址空间只有4GB4GB,而且是所有(操作系统内核、各个用户程序),而且是所有(操作系统内核、各个用户程序)代码所公用的!这种情况下,就必须对线性地址进行合理的规划代码所公用的!这种情况下,就必须对线性地址进行合理的规划了。了。页表管理(续)页表管理(续)n n页式地址转换的分析页式地址转换的分
29、析n n对于页式地址管理,由于页目录以及页表都存放在物理内存的页面中,对于页式地址管理,由于页目录以及页表都存放在物理内存的页面中,要进行地址变换就势必先要到内存中访问页目录和页表。由于要进行地址变换就势必先要到内存中访问页目录和页表。由于CPUCPU和内存和内存速度的不匹配,这样将势必极大地降低系统的效率。为了提高地址翻译速度的不匹配,这样将势必极大地降低系统的效率。为了提高地址翻译的速度,提高系统的效率,的速度,提高系统的效率,x86x86系统中设计了用于地址翻译的缓存来解决系统中设计了用于地址翻译的缓存来解决这一问题,这一缓存称为这一问题,这一缓存称为TLBTLB(Translation
30、 Look-aside bufferTranslation Look-aside buffer,即旁路转换,即旁路转换缓冲,或称为页表缓冲),在该缓存中存放了用于最近几次地址翻译的缓冲,或称为页表缓冲),在该缓存中存放了用于最近几次地址翻译的页表项,由于程序执行的局部性原理,下一次的地址转换往往跟上一次页表项,由于程序执行的局部性原理,下一次的地址转换往往跟上一次的地址转换采用的是同一个页目录表项和页表项),同时,由于的地址转换采用的是同一个页目录表项和页表项),同时,由于TLBTLB跟处跟处理器的距离更近,这样就极大地提高了地址翻译的效率和速度。理器的距离更近,这样就极大地提高了地址翻译的效
31、率和速度。n n但是,这样做可能存在一个潜在的问题:页目录(表)数据项的不一致但是,这样做可能存在一个潜在的问题:页目录(表)数据项的不一致性。以前系统里对应一个线性地址只有唯一的存放在内存中的页目录和性。以前系统里对应一个线性地址只有唯一的存放在内存中的页目录和页表,用于完成翻译的工作,但是,现在由于页表,用于完成翻译的工作,但是,现在由于TLBTLB的存在,系统可能在高的存在,系统可能在高速缓存中也存放了一份页表项数据,用于更快地对地址进行翻译,大多速缓存中也存放了一份页表项数据,用于更快地对地址进行翻译,大多数时候,它们是一致的,但是也有例外的情形。因为数时候,它们是一致的,但是也有例外
32、的情形。因为TLBTLB中的数据对于程中的数据对于程序员来说,是不可见的,程序对于页表项或者页目录项的修改并不能马序员来说,是不可见的,程序对于页表项或者页目录项的修改并不能马上反映到上反映到TLBTLB中,这样就可能导致错误的地址翻译,因为为了提高翻译的中,这样就可能导致错误的地址翻译,因为为了提高翻译的速度,处理器总是尽量地采用速度,处理器总是尽量地采用TLBTLB中的页表数据进行地址的翻译。所以,中的页表数据进行地址的翻译。所以,为了避免这种数据的不一致性所导致的地址翻译的错误情形的出现,系为了避免这种数据的不一致性所导致的地址翻译的错误情形的出现,系统程序员就必须在对页表进行修改后,使
33、统程序员就必须在对页表进行修改后,使TLBTLB中旧的页表数据失效。使其中旧的页表数据失效。使其失效的办法有两个,一个是重载失效的办法有两个,一个是重载CR3CR3,使整个,使整个TLBTLB中的数据都失效,也可中的数据都失效,也可以采用以采用invlpginvlpg指令。指令。页表管理(续)页表管理(续)n n页目录、页表和数据页的关联n nCode walk and implementationCode walk and implementationn npgdir_walk()pgdir_walk()n npage_lookup()page_lookup()n npage_remove(
34、)page_remove()n npage_insert()page_insert()n nboot_map_segment()boot_map_segment()页表管理(续)页表管理(续)n npgdir_walkpgdir_walkn npte_t*pgdir_walk(pde_t*pgdir,const void*va,int create)pte_t*pgdir_walk(pde_t*pgdir,const void*va,int create)n n检查虚拟地址(应该是线性地址)检查虚拟地址(应该是线性地址)vava已经能够用页表已经能够用页表(页目录(页目录+页表的体系)翻译,如
35、果能够,则返回该地页表的体系)翻译,如果能够,则返回该地址对应的页表项的地址;如果不能,同时址对应的页表项的地址;如果不能,同时create=0create=0的话,的话,则返回空(则返回空(NULLNULL);但是,如果);但是,如果create=1create=1的话,为该的话,为该地址创建对应的页表(因为没有实际物理页面相对应,地址创建对应的页表(因为没有实际物理页面相对应,即使创建,返回的页表项中的地址部分也为空!),即使创建,返回的页表项中的地址部分也为空!),并返回并返回vava所对应的页表项的地址。所对应的页表项的地址。n n注意:该函数返回的页表项地址为内核地址!注意:该函数返
36、回的页表项地址为内核地址!页表管理(续)页表管理(续)n npage_lookupn nstruct Page*page_lookup(pde_t*pgdir,void*va,struct Page*page_lookup(pde_t*pgdir,void*va,pte_t*pte_store)pte_t*pte_store)n n在页式地址翻译机制中查找线性地址在页式地址翻译机制中查找线性地址vava所对应所对应的物理页面,如果找到,则返回该物理页面,的物理页面,如果找到,则返回该物理页面,并将对应的页表项的地址放到并将对应的页表项的地址放到pte_storepte_store中;如中;如果
37、找不到,或其他原因,则返回空(果找不到,或其他原因,则返回空(NULLNULL)。)。页表管理(续)页表管理(续)n npage_removen nvoid page_remove(pde_t*pgdir,void*va)void page_remove(pde_t*pgdir,void*va)n n删除线性地址删除线性地址vava所对应的物理页面。所对应的物理页面。n n注意:在删除页面的时候,调用的是注意:在删除页面的时候,调用的是page_decrefpage_decref()(),仅减低该页面的引用度,而不一定要将页,仅减低该页面的引用度,而不一定要将页面删除。同时,由于页表项发生了修
38、改,删除面删除。同时,由于页表项发生了修改,删除操作完成后,应该调用操作完成后,应该调用tlb_invalidate()tlb_invalidate()更新更新TLBTLB。页表管理(续)页表管理(续)n npage_insertpage_insertn nint page_insert(pde_t*pgdir,struct Page*pp,void*va,int int page_insert(pde_t*pgdir,struct Page*pp,void*va,int perm)perm)n n这是这是JOSJOS在实现页面支持中最重要的一个函数,该函数在实现页面支持中最重要的一个函数,该
39、函数的功能是将页面管理结构的功能是将页面管理结构pppp所对应的物理页面分配给所对应的物理页面分配给线性地址线性地址vava。同时,将对应的页表项的。同时,将对应的页表项的permissionpermission设置设置成成PTE_P&permPTE_P&perm。n n注意:一定要考虑到线性地址注意:一定要考虑到线性地址vava已经指向了另外一个物已经指向了另外一个物理页面或者干脆就是这个函数要指向的物理页面的情理页面或者干脆就是这个函数要指向的物理页面的情况。如果线性地址况。如果线性地址vava已经指向了另外一个物理页面,则已经指向了另外一个物理页面,则先要调用先要调用page_remov
40、epage_remove将该物理页从线性地址将该物理页从线性地址vava处删除,处删除,再将再将vava对应的页表项的地址赋值为对应的页表项的地址赋值为pppp对应的物理页面。对应的物理页面。如果如果vava指向的本来就是参数指向的本来就是参数pppp所对应的物理页面,则将所对应的物理页面,则将vava对应的页表项中的物理地址赋值重新赋值为对应的页表项中的物理地址赋值重新赋值为pppp所对应所对应的物理页面的首地址即可。的物理页面的首地址即可。页表管理(续)页表管理(续)n nboot_map_segmentn nstatic void boot_map_segment(pde_t*pgdir
41、,static void boot_map_segment(pde_t*pgdir,uintptr_t la,size_t size,physaddr_t pa,int perm)uintptr_t la,size_t size,physaddr_t pa,int perm)n n在页表中,将线性地址在页表中,将线性地址la,la+sizela,la+size映射到物理映射到物理地址地址pa,pa+sizepa,pa+size。n n注意:注意:sizesize一定是一定是PGSIZE(4KB)PGSIZE(4KB)的整数倍。这个的整数倍。这个函数带来的疑问是:是否有可能有一个物理页函数带来的
42、疑问是:是否有可能有一个物理页面,它已经被分配作为存储页表的页面了,但面,它已经被分配作为存储页表的页面了,但由于在由于在pa,pa+sizepa,pa+size范围内,所以又被用来成为范围内,所以又被用来成为某线性地址对应的物理页面了?!某线性地址对应的物理页面了?!页表管理(续)页表管理(续)n nJOSJOS的线性地址规划的线性地址规划页表管理(续)页表管理(续)n n按照按照JOSJOS的要求,一共有三个线性地址到物理地址的要求,一共有三个线性地址到物理地址的映射是必须的:的映射是必须的:n nUPAGES,sizeof(PAGES)=pages,sizeof(PAGES)UPAGES
43、,sizeof(PAGES)=pages,sizeof(PAGES)n n这里这里PAGESPAGES代表页面管理结构所占用的空间;代表页面管理结构所占用的空间;n nKSTACKTOP KSTKSIZE,8=bootstack,8KSTACKTOP KSTKSIZE,8=bootstack,8n n其中其中bootstackbootstack为内核编译时预先留下的为内核编译时预先留下的8 8个页面(用做内核堆个页面(用做内核堆栈);栈);n nKERNBASE,pages in the memory=0,pages in the KERNBASE,pages in the memory=0,
44、pages in the memorymemoryn n这个地址映射范围比较广,含盖了所有物理内存。这个地址映射范围比较广,含盖了所有物理内存。n n其中,最后一个地址映射最重要,因为其中,最后一个地址映射最重要,因为JOSJOS其后启动新其后启动新的段式地址,新的段的段式地址,新的段base=0 x0base=0 x0(见(见struct Segdesc gdtstruct Segdesc gdt),),如果没有这个地址映射,以前的内核地址(如果没有这个地址映射,以前的内核地址(0 xf00000000 xf0000000开始的地址是无法变换到实际的物理地址的)!开始的地址是无法变换到实际的物理地址的)!本章结束