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

FY

Johnson 's Blog

 
 
 

日志

 
 

[原创]linux0.12 sleep_on解答  

2016-10-06 16:30:55|  分类: Linux内核 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


 

进程:

资源:椅子

进行等待资源:人坐在椅子上等待

 

我们知道,多个进程在等待同一个资源,资源只有1个,即只有1把椅子,坐在这个椅子上的表示最近等待这个资源的进程。

隐含的等待这个资源的一个进程链表是:D (坐在椅子上)? C ? B ? A(最先等待的进程)

A最先调用sleep_on(椅子)时,椅子上空的,没人坐在椅子上,于是A的将现在椅子上等待的“空进程地址保存到自己内核堆栈上(sleep_on的函数栈上),然后将自己A坐到等待椅子上。调用schedule切换到其他任务。

同样的,接着B进程也等待该资源,于是

B调用sleep_on(椅子)时,A坐在椅子上,于是B的将现在椅子上等待的B进程地址保存到自己内核堆栈上(sleep_on的函数栈上),然后将自己B坐到等待椅子上。调用schedule切换到其他任务。

最后形成了一个隐形的链。

那么,将来某一时刻,这个资源被唤醒了

Wake_up(椅子),它将现在坐在这个椅子上的D进程唤醒(状态state =0)

但是现在进程可能不是D进程,等将来D进程被真正调度运行时,它从schedule这个函数处返回,往下执行,为什么有下面一段处理?为了什么?

repeat:  schedule();

if (*p && *p != current) {

              (**p).state = 0;

              current->state = TASK_UNINTERRUPTIBLE;

              goto repeat;

       }

解答:在wakeup时,D进程确实状态设为state = 0,但是如果到D进程真正被调度这期间,又有另一个进程E也等待该资源的话,E会把自己推上椅子,而把当时还在椅子上的D保存到E自己的堆栈上。

这样一来,D运行时,发现现在椅子上坐着的(*p内容)和现在进程current(也就是D)不相等,则进程D继续sleep,但是会把当前椅子上的进程唤醒:(**p).state = 0; 因为如果D不理会,而直接往下处理,D就会把自己堆栈上保存的进程(C)推上椅子,这样原先椅子上的E就被无缘无故的挤掉了,挤出了这个等待链,将来再也不会被唤醒了。

本质是,一个资源的等待链表,在唤醒时必须要从这个链接的椅子上开始真正的唤醒

所谓真正,是指我这个当前进程被唤醒,从schedule继续往下执行了,并且还要保证我这个当前进程也的确当前这个链的椅子上的那个进程。

 

附:

void wake_up(struct task_struct **p)

{

       if (p && *p) {

              if ((**p).state == TASK_STOPPED)

                     printk("wake_up: TASK_STOPPED");

              if ((**p).state == TASK_ZOMBIE)

                     printk("wake_up: TASK_ZOMBIE");

              (**p).state=0;

       }

}

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

历史上的今天

在LOFTER的更多文章

评论

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

页脚

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