注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

FY

Johnson 's Blog

 
 
 

日志

 
 

[原创]LINUX 0.12笔记  

2016-10-05 12:57:42|  分类: Linux内核 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

代码执行流是代码执行流,代码的运行特权级是特权级,这2个东西是完全不相关的2个概念。只是由于我们人为的将运行在特权级0的代码视为内核,运行在特权级3的代码视为用户程序,且将这2个代码人为的分开,分配在不同的段中。这样伴随着特权级的变化 ,代码控制执行流也会被跳转。也就是我们常认为的“代码从用户态跳转到内核态中去啦“这样的观点。我们知道上电后运行在特权级0,我们通过move_to_user_mode来将代码的运行特权级从0改为3,但此时代码执行流并没有改变哦,还是接着往下继续运行。所以特权级改变和代码控制跳转并没有直接关系。

 

一直强调任务0fork后不能写堆栈,只是为了任务1fork返回后,到第一次真正被调用运行时,它的运行环境(包括堆栈)和任务0fork返回时的环境一模一样。这也正是fork的意义。但由于内核在处理任务0,任务1时作了特殊处理:

fork后,父进程任务0对数据段、堆栈段页面权限依旧是可读可写,而子进程任务1对数据段,堆栈段页面权限是只读。

又由于不知道下次任务1什么时候被调度。所以不管任务1后来有没有对页面进行写操作从而产生页保护异常。任务1都希望从fork返回后的环境还是没有改变。

Fork后,任务0先被调度

任务0对堆栈进行了修改,造成堆栈改变

接着任务1被调度并运行,它从fork返回

情况1

任务1不对堆栈进行写操作,它只使用堆栈。这时它只是读取,所以使用的还是任务0的堆栈段中的数据,但它已被任务0改变了。

情况2

任务1对堆栈进行写操作,从而产生页保护异常,内核为任务1新申请一页物理内存,将它们共享的数据内容拷贝到新页面中,完成页映射后再给任务1使用。这时拷贝过来的堆栈数据也是已被任务0改变了

 

在对任务1以后的任务进行fork时,父进程A和子进程B都被设置为只读

并且内核会记录对这一页面的引用加1,表示有2个进程在使用这个页面。

mem_map[this_page]++

接着,父进程A对这一页面进行写操作,触发页保护异常中断,

在中断处理中进行do_wp_page –un_wp_page

它会判断,当前这个页面的引用为2,所以重新申请一页内存,将原先共享的页面中数据拷贝到新页中,重新设置页表映射,并将这共享页面的引用数减1

 

接着 子进程B也对这一页面进行写操作,同样触发页保护异常中断,

在中断处理中进行do_wp_page –un_wp_page

它会判断,当前这个页面的引用为1,所以只需要把产生页保护异常的页面的权限设为可读可写就可以了。

 

这样达到了在fork锁住了数据段页面,保证父进程子进程任何一个进行写操作后,两个进程都可以得到正确的数据,而不会相互污染对方的数据。

  评论这张
 
阅读(4)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017