do_wp_page函数由页保护异常过程调用,用来处理页保护异常。该函数里面直接调用un_wp_page函数。
void un_wp_page(unsigned long * table_entry)
{
unsigned long old_page,new_page;
old_page = 0xfffff000 & *table_entry;
if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
*table_entry |= 2;
invalidate();
return;
}
if (!(new_page=get_free_page()))
oom();
if (old_page >= LOW_MEM)
mem_map[MAP_NR(old_page)]--;
*table_entry = new_page | 7;
invalidate();
copy_page(old_page,new_page);
}
/*
* This routine handles present pages, when users try to write
* to a shared page. It is done by copying the page to a new address
* and decrementing the shared-page counter for the old page.
*
* If it's in code space we exit with a segment error.
*/
void do_wp_page(unsigned long error_code,unsigned long address)
{
#if 0
/* we cannot do this yet: the estdio library writes to code space */
/* stupid, stupid. I really want the libc.a from GNU */
if (CODE_SPACE(address))
do_exit(SIGSEGV);
#endif
un_wp_page((unsigned long *)
(((address>>10) & 0xffc) + (0xfffff000 &
*((unsigned long *) ((address>>20) &0xffc)))));
}
之前文章对un_wp_page函数的实参作了简要分析:https://blog.csdn.net/sunxiaohusunke/article/details/88717146
本文对这个函数的功能,做概要描述,以便对该函数的功能有直观感受:
d_wp_page函数对异常的线性地址对应的物理页面进行检验,首先判断是否存在共享,如果没有,直接设置页面为可读可写,然后刷新页缓冲之后返回。如果有共享,则通过get_free_page函数取得一页新的物理页面,然后取消共享,将新的页表项设置为这个新页的地址,刷新缓冲,然后将旧页面的内容复制到新页面。