页写保护
来源:互联网 发布:linux服务器开通外网 编辑:程序博客网 时间:2024/05/01 22:31
1、进程A和进程B共享页面,代码如下:
if (!(pid=fork())) {压栈操作;//子进程B}if (pid>0){ 压栈操作;//父进程A}
2、我们假设现在系统有一个用户进程A,他自己对应的程序代码已经载入内存中,此时该进程内存中所占用的页面引用计数都为”1“,接下来他开始执行,通过调用fork函数创建一个新进程(进程B)。在新进程创建的过程中,系统将进程A的页表项全部复制给进程B,并设置进程B的页目录项。此时这两个进程就共享页面,被共享页面的引用计数累加为2,并将此共享页面全部设置为”只读“属性,即无论是进程A还是进程B,都只能对这些共享的页面进程读操作,而不能进行写操作。执行代码如下:
int copy_page_tables(unsigned long from,unsigned long to,long size){......for( ; size-->0 ; from_dir++,to_dir++) {......for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {this_page = *from_page_table;if (!(1 & this_page))continue;this_page &= ~2;//进程A对页面的操作属性被设置为只读*to_page_table = this_page;//进程B对页面的操作属性被设置为只读if (this_page > LOW_MEM) {*from_page_table = this_page;this_page -= LOW_MEM;this_page >>= 12;mem_map[this_page]++;//引用计数记录在mem_map中,累加为2}}}invalidate();return 0;}
3、我们假设接下来轮到进程A执行,进程A接下来的动作是一个压栈动作,现在看看会发生什么。
现在进程A的程序对应的所有页面都是只读状态的。压栈是个写操作,所以会产生”页写保护“异常,”页写保护“中断对应的服务程序时up_wp_page()函数。
函数执行时,先要在主内存中申请一个空闲页面(以后我们称之为新页面),以便备份刚才压栈的位置所在页面(以后我们称之为原页面)的全部数据,然后将原页面的引用计数减1。
代码如下:
void un_wp_page(unsigned long * table_entry)//页表项,现在指向原页面{unsigned long old_page,new_page;old_page = 0xfffff000 & *table_entry;......if (!(new_page=get_free_page()))//申请到新页面oom();if (old_page >= LOW_MEM)mem_map[MAP_NR(old_page)]--;//页面引用计数递减1*table_entry = new_page | 7; //7的二进制形式为111,标志着新页面可读可写了,将进程A的页表项指向新申请的页面invalidate();copy_page(old_page,new_page);//复制原页面的内容到进程A新申请的页面}
4、将进程A的页表项指向新申请的页面,代码是*table_entry = new_page | 7;
5、复制原页面的内容到进程A新申请的页面,代码是copy_page(old_page,new_page);如下图:
6、进程A在用户空间开始执行压栈,仿佛什么都没有发生,压栈的数据却已经压入了新申请的页面。
7、进程A执行一段时间后,时钟中断就该轮到他的子进程--进程B执行了,进程B仍然使用着原页面。进行压栈操作,也会出现”页写保护“异常,执行up_wp_page()函数。由于原页面的引用计数已经被削减为1了,所以现在就要将原页面的属性设置为”可读可写“,如下:
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;//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)]--;*table_entry = new_page | 7;invalidate();}
进程B在用户空间开始执行压栈,仿佛什么都没有发生,压栈的数据却已经压入了原页面。
最后形成如下图: 8、进程A和进程B在压栈数据的处理方面可以操作不同的页面了。这些页面都是可读可写的,而且引用计数都为1,以后彼此都不会干扰对方。
现在进程B并没有自己的程序,如果将来它有了自己的程序,就会和原页面解除关系,原页面的引用计数将会继续减1,于是变成0,系统将认定他为”空闲页面“,可以重新用于分配。
- 页写保护
- 磁盘写保护
- 【基础】关于const写保护
- U盘写保护解决方案
- U盘写保护恢复
- u盘被写保护
- 取消U盘写保护
- 硬盘写保护方案
- Excel 写保护方法
- SD卡写保护原理
- 优盘被写保护解决方案
- isp下载写保护
- U盘写保护怎么办
- 磁盘写保护,只读,怎么办?
- 内存卡写保护问题
- u盘去掉写保护
- MT7620A 解除写保护
- SSDT HOOK 内存写保护
- 基于android4.0 USB gadget框架分析
- 进入Actiity中不让软键盘弹出
- poj_3187_Backward Digit Sums
- 在不同数据库中如何删除已存在的表的脚本写法
- 集合实例化方法+方法或-方法
- 页写保护
- 欢迎使用CSDN-markdown编辑器
- android应用开发学习纪实(4)(火箭一般的android模拟器genymotion的使用)
- Gamification MOOC 学习笔记4——动机与心理(上)
- 简单易懂的Dancing links讲解(1)
- 转载自:http://blog.csdn.net/lmj623565791/article/details/24015867
- 安卓基础(四)
- Android下setLatestEventInfo警告、Handler警告、SimpleDateFormat警告
- LigerUi中表(Grid)控件的相关属性笔记(持续添加中)