在i386CPU将一个线性地址映射成物理地址的过程中如果页面该地址的映射已经建立,但是发现相应页面表项或目录项中的P(present)标志位为0;表示相应的物理页面不在内存中。只有P标志位为0就都认为页面映射是失败的,其他字段没有意义。
-- do_page_fault() > handle_mm_fault( ) > handle_pte_fault( )
在 handle_pte_fault( )中首先检查P的标志位,<1>如果为0,再检查表项是否为空,即全0;如果为空那么就说明映射尚未建立。<0>不为空则说明页面已经映射,在交换设备上。通过do_swap_page( )从交换设备上换入这个页面。
-- do_page_fault() > handle_mm_fault( ) > handle_pte_fault( ) > do_swap_page( )
处理页面异常时,首先要看看相应的内存页面是否还留在swapper_space上换入换出队列中尚未释放,<1>如果是,则先调用lookup_swap_cache()。<0>如果没找到那就说明已经释放了,内容只能在盘上。那就通过read_swap_cache()分配一个内存页面。在此之前会先调用swapin_readahead( )(从磁盘上读时会进行预读,通常链入了活跃页面队列)。无论swapin_readahead( )还是read_swap_cache()都会将gfp_mask的_ _GFP_WAIT置为1,当分配不到内存页面时,让内核调度其他进程先运行(其他进程可能换出空间),再次分配页面很有可能成功,如果失败就do_swap_page()失败了返回-1。
-- do_page_fault() > handle_mm_fault( ) > handle_pte_fault( ) > do_swap_page( ) > read_swap_cache( )
这个函数中调用了两次lookup_swap_cache( ),第一次从swapper_space寻找一次,(节省一次从设备上读,防止同一页面在内存上有两个副本);第二次防止当前进程在等待期间读入了页面,所以再检查一遍。需要从交换设备中读入就通过add_to_swap_cache()将新分配的物理页面(它的page结构)挂入swapper_space队列以及active_list中。