linux0.11是如何处理页异常的?
时间:2007-04-10 来源:pywj777
1. linux0.11是如何处理页异常的?
(1) 答:当产生页异常时,会调用page_fault中断处理程序。该中断处理程序主要分两种情况处理,一是由缺页引起的页异常中断,通过调用do_no_page(error_code, address)进行处理,二是由页写保护引起的页异常,此时调用页写保护处理函数do_wp_page(error_code, address)进行处理。其中的出错码error_code是由CPU自动产生并压入堆栈中的。出现异常时访问的线性地址address是从控制寄存器CR2取得的,CR2是专门用来存放出错时的线性地址。
(2) 因为在内核创建进程时,新进程与父进程被设置成共享代码和数据内存页面,并且所有这些页面均被设置成只读页面。而当新进程或原进程需要向内存页面写数据时,CPU就会检测到这个情况并产生页面写保护异常。
(3) do_wp_page()首先根据传递过来的页面线性地址address参数求出该线性地址指定的页面在页表中的页表项指针。然后用这个值调用up_wp_page()。
(4) up_wp_page()首先判断要写的页面是否被共享,若没有,则把页面设置为可写,然后退出。若页面处于共享状态,则需要重新申请一新页面,并复制被写页面内容,以供写进程单独使用。共享被取消。
(5) do_no_page()执行缺页处理,它首先查看是否是于进程动态申请内存页面,若是则只需映射一页物理内存即可,若不是则调用share_page()尝试与加载的相同文件进行页面共享。若共享不成功,那么只能从相应文件中读入所缺的数据页面到指定的线性地址处,它是根据缺页的地址计算出缺少的页面在执行映像文件中的起始块号。根据这个块号和执行文件的i节点,可以找到对应的设备逻辑块号。然后利用bread_page()将这4个逻辑块读入物理内存。
(6) share_page()共享页面处理,该函数根据当前进程任务数据结构中的executable字段指定的i节点的引用次数i_count是否大于1来判断系统中是否有另一个进程也在执行同一个执行文件。若有,则在系统当前所有任务中寻找这样的任务,其executable字段值与当前进程的形同。然后调用try_to_share()尝试页面共享。
(7) try_to_share()尝试对当前指定地址处的页面进行共享处理。若被共享进程的指定地址处的页面存在并且没有被修改过的话,就让当前进程与其共享。共享的方法是首先对被共享进程的页表项进行修改,设置其写保护(R/W=0,只读)标志。然后让当前进程复制该进程的这个页表项,此时当前进程与被共享进程都映射到同一物理页面上。随后刷新页变换高速缓冲,计算所操作物理页面的页面号,并将对应页面映射字节数组项中的引用递增1,共享成功。