内核版本:linux 0.11
函数定义:memory.c第247行
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)))));
}
do_wp_page()函数有两个参数,第一个是错误码,第二个是线性地址值。
该函数内部直接调用un_wp_page()函数,该函数参数是(unsigned long * table_entry),是页表项指针值。
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);
}
do_wp_page()函数中构造了un_wp_page的页表项指针参数,其中
(0xfffff000 & *((unsigned long *)((address>>20) &0xffc)))
是为了取得页目录表中的页目录项里面指定的20位页表基地址。其中
((address>>10) & 0xffc)
是为了取得线性地址页表项的4字节对齐索引地址,第一项是0,第二项是4,然后8,12,16,以此类推。此值加上页表基地址,就是页表项对应的地址指针了。