日期:2014-05-16 浏览次数:20847 次
1、用户进程与内存管理
父子进程共享同一页面,如果这个页面设置为可写状态,那么两个进程同时写一个页面会造成混乱,所以此时页表表项后三位设置为101,U/S=1,
R/W=0,P=1。对应代码如下:
代码路径:mm/memory.c
int copy_page_tables(unsigned long from,unsigned long to,long size)
{
...
for( ; size-->0 ; from_dir++,to_dir++) {
if (1 & *to_dir)
panic("copy_page_tables: already exist");
if (!(1 & *from_dir))
continue;
from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
if (!(to_page_table = (unsigned long *) get_free_page()))
return -1; /* Out of memory, see freeing */
*to_dir = ((unsigned long) to_page_table) | 7;
nr = (from==0)?0xA0:1024;
for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
this_page = *from_page_table;
if (!(1 & this_page))
continue;
this_page &= ~2;//页表项中的R/W位被设置为0,~2为101
*to_page_table = this_page;
if (this_page > LOW_MEM) {
*from_page_table = this_page;
this_page -= LOW_MEM;
this_page >>= 12;
mem_map[this_page]++;//父子进程共享,引用计数记录在mem_map中,累加为2
...
}
如果父子进程都要写页面,该怎么办呢?
假设进程A是父进程,B是子进程。进程A要往共享页面写数据,因为该页面为只读,会产生页写保护,页写保护为进程A申请新页面,并且引用计数递
减1,并让进程A的页表中指向原页面的页表项改为指向新页面,并将其使用的属性从“只读”改变为“可读可写”,一切准备就绪后,将原页面中的内容复制到新页面中。具体结果如下图:

进程A执行一段时间后,就该轮到它的子进程-进程B执行了。进程B仍然使用着原页面。假设也要在原页面总进程写操作,但是现在原页面的属性仍然
是“只读”的,这一点在进程A创建B时就是这样设置的,一直都没有改变过。所以在这种情况下,又需要进程页写保护,由于原页面的引用计数已经被消减为1了 ,所以现在就要将院页面的属性设置为“可读可写”。如下图:

页写保护,代码路径:mm/memory.c
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) {//发现原页面引用计数为1,不用共享了
*table_entry |= 2;//010,R/W位设置为1,可读可写
invalidate();
return;
}
if (!(new_page=get_free_page()))//申请到新页面
oom();
if (old_page >= LOW_MEM)
mem_map[MAP_NR(old_page)]--;//页面引用计数递减1
*table_entry = new_page | 7;//111,标志着新页面可读可写了
invalidate();
copy_page(old_page,new_page);//将原页面内容复制给进程A新申请的页面
}
进程切换,一是时间片到了,切换,且只有在3特权级下才能切换,0特权级下不能切换;二是等待硬盘读盘时,要切换到其他进程。
代码路径:kernel/sched.c