2.5 页表处理
pte_t、pmd_t、pud_t和pgd_t分别描述页表项、页中间目录项、页上级目录和页全局目录项的类型格式。当PAE被激活时它们都是64位的数据类型,否则都是32位数据类型。pgprot_t是另一个64位(PAE激活时)或32位(PAE禁用时)的数据类型,它表示与一个单独表项相关的保护标志。
五个类型转换宏(__ pte、__ pmd、__ pud、__ pgd和__pgprot)把一个无符号整数转换成所需的类型。另外的五个类型转换宏(pte_val,pmd_val, pud_val,pgd_val和pgprot_val)执行相反的转换,即把上面提到的四种特殊的类型转换成一个无符号整数。
内核还提供了许多宏和函数用于读或修改页表表项:
• 如果相应的表项值为0,那么,宏pte_none、pmd_none、pud_none和pgd_none产生的值为1,否则产生的值为0。
• 宏pte_clear、pmd_clear、pud_clear和pgd_clear清除相应页表的一个表项,由此禁止进程使用由该页表项映射的线性地址。ptep_get_and_clear()函数清除一个页表项并返回前一个值。
•set_pte,set_pmd,set_pud和set_pgd向一个页表项中写入指定的值。set_pte_atomic与set_pte作用相同,但是当PAE被激活时它同样能保证64位的值能被原子地写入。
• 如果a和b两个页表项指向同一页并且指定相同访问优先级,pte_same(a,b)返回1,否则返回0。
• 如果页中间目录项指向一个大型页(2MB或4MB),pmd_large(e)返回1,否则返回0。
宏pmd_bad由函数使用并通过输入参数传递来检查页中间目录项。如果目录项指向一个不能使用的页表,也就是说,如果至少出现以下条件中的一个,则这个宏产生的值为1:
• 页不在主存中(Present标志被清除)。
• 页只允许读访问(Read/Write标志被清除)。
• Acessed或者Dirty位被清除(对于每个现有的页表,Linux总是强制设置这些标志)。
pud_bad宏和pgd_bad宏总是产生0。没有定义pte_bad宏,因为页表项引用一个不在主存中的页,一个不可写的页或一个根本无法访问的页都是合法的。
如果一个页表项的Present标志或者PageSize标志等于1,则pte_present宏产生的值为1,否则为0。前面讲过页表项的PageSize标志对微处理器的分页部件来讲没有意义,然而,对于当前在主存中却又没有读、写或执行权限的页,内核将其Present和PageSize分别标记为0和1。这样,任何试图对此类页的访问都会引起一个缺页异常,因为页的Present标志被清0,而内核可以通过检查PageSize的值来检测到产生异常并不是因为缺页。
如果相应表项的Present标志等于1,也就是说,如果对应的页或页表被装载入主存,pmd_present宏产生的值为1。pud_present宏和pgd_present宏产生的值总是1。
下表中列出的函数用来查询页表项中任意一个标志的当前值;除了pte_file()外,其他函数只有在pte_present返回1的时候,才能正常返回页表项中任意一个标志。
函数名称 | 说明
| pte_user( )
| 读 User/Supervisor 标志。
| pte_read( )
| 读 User/Supervisor 标志(表示 80x86 处理器上的页不受读的保护)。
| pte_write( )
| 读 Read/Write 标志。
| pte_exec( )
| 读 User/Supervisor 标志( 80x86 处理器上的页不受代码执行的保护)。
| pte_dirty( )
| 读 Dirty 标志。
| pte_young( )
| 读 Accessed 标志。
| pte_file( )
| 读 Dirty 标志(当 Present 标志被清除而 Dirty 标志被设置时,页属于一个非线性磁盘文件映射)。
|
|