分类: 嵌入式
2011-08-14 19:37:09
handle_pte_fault()
上文最后提到了handle_pte_fault()这个函数,用来处理页错,分配PTE。为了更清楚的了解PTE是如何申请到的,还是有必要深究一下。
handle_pte_fault()有几个函数用来检查当前pte的状态:
pte_present() 检测页面是否在内存中
pte_none() 检测页表项是否为空
pte_file() 同一地址多映射(此函数不重要)
vm->ops->fault标记位
内核用likely对其做了标记,说明这个标记一般满足,适用于已经建立好虚拟内存和文件的映射关系的情况。
1)针对满足pte_present()函数,即PTE不在内存中,会在以4个下函数中选择一个进行处理:
(1)do_linear_fault();
最常见的情况,PTE表项为空,但满足vm->ops->fault,说明已经在内存中建立虚拟内存和文件的映射关系。
(2)do_anonymous_page();
PTE表项为空,但是没有建立映射关系,说明是第一次demanding page。
(3)do_nonlinear_fault();
PTE表项非空,满足pte_file()检查,对同一个物理地址做多个虚拟映射。
(4)do_swap_page();
PTE表项非空,不满足pte_file()检查,此页将会被换出。
2)如果不满足pte_present(),即PTE在内存中,则会执行下面的COW操作:
COW的全称叫做“copy on write”,即写时复制。这一块是涉及到两个进程共享操作的,简单的说两个进程可以共享页面(特别是fork出的进程),只有当一个进程需要写入文件时,才从同一页面复制一份副本。下面的函数调用do_wp_page(),将生成的复制页赋值给写进程。由于我仅仅跟中了系统的“/sbin/init”,所以这里根本没有调用到。
附:
do_anonymous_page()函数的跟踪
——>mk_pte() 构建映射表
——>ptn_pte()
——>__pte((ptn << 12 | pgprot_val)
最终生成的PTE为32bit,其中20bit物理地址,12bit控制信息。