日期:2014-05-16 浏览次数:20637 次
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