作家
登录

设置Linux进程的睡眠和唤醒

作者: 来源: 2017-08-02 16:54:05 阅读 我要评论

spin_lock(&list_lock); 
  •  
  • list_add_tail(&list_head, new_node); 
  •  
  • spin_unlock(&list_lock); 
  •  
  • wake_up_process(processa_task);  
  • 避免无效唤醒

    若何避免无效唤醒问题呢?我们发明无效唤醒重要产生在检查前提之后和过程状况被设置为睡眠状

    的过程构造。set_current_state()将该过程的状况大年夜履行状况TASK_RUNNING 变成睡眠状况

    态之前, 本来B过程的wake_up_process()供给了一次将A过程状况置为TASK_RUNNING 的机会,可惜这个时刻A过程的状况仍然是TASK_RUNNING,所以wake_up_process()将A过程状况大年夜睡眠状况改变为运行状况的尽力 没有起到预期的感化。要解决这个问题,必须应用一种保障机制使得断定链表为空和设置过程状况为睡眠状况成为一个弗成瓜分的步调才行,也就是必须清除竞争条 件产生的根源,如许在这之后出现的wake_up_process ()就可以起到唤醒状况是睡眠状况的过程的感化了。

    找到了原因后,从新设计一下A过程的代码构造,就可以避免膳绫擎例子中的无效唤醒问题了。

    A过程:

    1. set_current_state(TASK_INTERRUPTIBLE); 
    2.  
    3. spin_lock(&list_lock); 
    4.  
    5. if(list_empty(&list_head)) { 
    6.  
    7. spin_unlock(&list_lock); 
    8.  
    9. schedule(); 
    10.  
    11. spin_lock(&list_lock); 
    12.  
    13.  
    14. set_current_state(TASK_RUNNING); 
    15.  
    16.  /* Rest of the code ... */ 
    17.  
    18. spin_unlock(&list_lock);  

    了链表为空今后调用wake_up_process(),那么A过程的状况就会主动由本来TASK_INTERRUPTIBLE

    变成TASK_RUNNING,此后即使过程又调用了schedule(),因为它如今的状况是TASK_RUNNING,所以仍然不会被大年夜运行队列中移出,因而不会缺点的进入睡眠,当瘸就镣避免了无效唤醒问题。

    另一种是弗成中断 的睡眠状况,其状况标记位为TASK_UNINTERRUPTIBLE。可中断的睡眠状况的过程会睡眠直到某个前提变为真,比如说产生一个硬件中断、释放 过程正在等待的体系资本或是传递一个旌旗灯号都可所以唤醒过程的前提。弗成中断睡眠状况与可中断睡眠状况类似,然则它有一个例外,那就是把旌旗灯号传递到这种睡眠 状况的过程不克不及改变它的状况,也就是说它不响应旌旗灯号的唤醒。弗成中断睡眠状况一般较罕用到,但在一些特定情况下这种状况照样很有效的,比如说:过程必须等 待,不克不及被中断,直到某个特定的事宜产生。

    Linux内核的例子

    在Linux操作体系中,内核的稳定性至关重要,为了避免在Linux操作体系内核中出现无效唤醒问题,

    Linux内核在须要过程睡眠的时刻应当应用类似如下的操作:

    1. /* ‘q’是我们欲望睡眠的等待队列 */ 
    2.  
    3. DECLARE_WAITQUEUE(wait,current); 
    4.  
    5. add_wait_queue(q, &wait); 
    6.  
    7. set_current_state(TASK_INTERRUPTIBLE); 
    8.  
    9. /* 或TASK_INTERRUPTIBLE */ 
    10.  
    11. while(!condition) /* ‘condition’ 是等待的前提*/ 
    12.  
    13. schedule(); 
    14.  
    15. set_current_state(TASK_RUNNING); 
    16.  
    17. remove_wait_queue(q, &wait);  

    这里会出现一个问题,假如当A过程履行到第3行后第4行前的时刻,B过程被别的一个处理器调剂

    膳绫擎的操作,使得过程经由过程下面的一系列步调安然地将本身参加到一个等待队列中进行睡眠:起首调

    用DECLARE_WAITQUEUE ()创建一个等待队列的项,然后调用add_wait_queue()把本身参加到等待队列中,并且将过程的状况设置为 TASK_INTERRUPTIBLE 或者TASK_INTERRUPTIBLE。然后轮回检查前提是否为真:如不雅是的话就没有须要睡眠,如不雅前提不为真,就调用schedule()。当过程 检查的前提知足后,过程又将本身设置为TASK_RUNNING 并调用remove_wait_queue()将本身移出等待队列。

    大年夜膳绫擎可以看到,Linux的内核代码保护者也是在过程检查前提之前就设置过程的状况为睡眠状况,

    然后才轮回检查前提。如不雅在过程开端睡眠之前前提就已经杀青了,那么轮回会退出场用set_current_state()将本身的状况设置为就绪,如许同样包管了过程不会存在缺点的进入睡眠的偏向,当瘸就镣不会导致出现无效唤醒问题。


      推荐阅读

      NoSQL: 如何在Ubuntu 16.04上安装OrientDB

    启动 OrientDB 并使其开机自启动:解释 - 非关系型数据库(NoSQL)和 OrientDB平日在我们说起数据库的时刻,想到的昵嘟个重要的分类:应用用于用户和应用法度榜样之间进行对接的一种被称为构>>>详细阅读


    本文标题:设置Linux进程的睡眠和唤醒

    地址:http://www.17bianji.com/lsqh/36520.html

    关键词: 探索发现

    乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

    网友点评
    自媒体专栏

    评论

    热度

    精彩导读
    栏目ID=71的表不存在(操作类型=0)