作家
登录

设置Linux进程的睡眠和唤醒

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

TASK_INTERRUPTIBLE。 如不雅schedule()是被一个状况为TASK_RUNNING 的过程调剂,那么schedule()将调剂别的一个过程占用CPU;如不雅schedule()是被一个状况为TASK_INTERRUPTIBLE 或TASK_UNINTERRUPTIBLE 的过程调剂,那么还有一个附加的步调将被履行:当前履行的过程在别的一个过程被调剂之前会被大年夜运行队列中移出,这将导致正在运行的那个过程进入睡眠,因为 它已经不在运行队列中了。

在Linux中,仅等待CPU时光的过程称为就绪过程,它们被放置在一个运行队列中,一个就绪过程的状 态标记位为TASK_RUNNING。一旦一个运行中的过程时光片用完, Linux 内核的调剂器会剥夺这个过程对CPU的┞菲握权,并且大年夜运行队列中选择一个合适的过程投入运行。

当然,一个过程也可以主动释放CPU的┞菲握权。函数 schedule()是一个调剂函数,它可以被一个过程主动调用,大年夜而调剂其它过程占用CPU。一旦这个主动放弃CPU的过程被从新调剂占用 CPU,那么它将大年夜前次停止履行的地位开端履行,也就是说它将大年夜调用schedule()的下一行代码处开端履行。

有时刻,过程须要等待直到某个特定的事宜产生,例如设备初始化完成、I/O 操作完成或准时器到时等。在这种情况下,过程则必须大年夜运行队列移出,参加到一个等待队列中,这个时刻过程就进入了睡眠状况。

投 入运行。在这个时光片内,B过程履行完了它所有的指令,是以它试图唤醒A过程,而此时的A过程还没有进入睡眠,所以唤醒操作无效。在这之后,A 过程持续履行,它会缺点地认为这个时刻链表仍然是空的,于是将本身的状况设置为TASK_INTERRUPTIBLE然后调用schedule()进入睡 眠。因为错过了B过程唤醒,它将会无穷期的睡眠下去,这就是无效唤醒问题,因为即使链表中稀有据须要处理,A 过程也照样睡眠了。

Linux 中的过程睡眠状况分类

一种是可中断的睡眠状况,其状况标记位TASK_INTERRUPTIBLE;

在现代的Linux操作体系中,过程一般都是用调用schedule()的办法进入睡眠状况的,下面的代码演

示了若何让正在运行的过程进入睡眠状况。

  1. sleeping_task = current
  2.  
  3. set_current_state(TASK_INTERRUPTIBLE); 
  4.  
  5. schedule(); 
  6.  
  7. func1(); 
  8.  
  9. /* Rest of the code ... */  

在第一个语句中,法度榜样存储了一份过程构造指针sleeping_task,current 是一个宏,它指向正在履行

我们可以应用下面的┞封个函数将刚才那个进入睡眠的过程唤醒。

  1. wake_up_process(sleeping_task); 

在调用了wake_up_process()今后,这个睡眠过程的状况会被设置为TASK_RUNNING,并且调剂器

会把它参加到运行队列中去。当然,这个过程只有鄙人次被调剂器调剂到的时刻才能真正地投入运行。

无效唤醒

几乎在所有的情况下,过程都邑在检查了某些前提之后,发明前提不知足才进入睡眠。可是有的时刻

过程却会在 剖断前提为真后开端睡眠,如不雅如许的话过程就会无穷期地休眠下去,这就是所谓的无效唤醒问题。在操作体系中,当多个过程都妄图对共享数据进行某种处理,而 最后的结不雅又取决于过程运行的次序时,就会产生竞争前提,这是操作体系一一个典范的问题,无效唤醒恰好就是因为竞争前提导致的。

假想有两个过程A 和B,A 过程正在处理一个链表,它须要检查这个链表是否为空,如不雅不空就对链

表琅绫擎的数据进行一些操作,同时B过程也在往这个链表添加节点。当这个链表是空的时刻,因为无数据可操作,这时A过程就进入睡眠,当B过程向链表琅绫擎添加了节点之后它就唤醒A 过程,其代码如下:

可以看到,这段代码在测试前提之前就将当前履行过程状况转设置成TASK_INTERRUPTIBLE了,并且在链表不为空的情况下又将本身置为TASK_RUNNING状况。如许一来如不雅B过程在A过程过程检查

A过程:

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

B过程:


  1.   推荐阅读

      NoSQL: 如何在Ubuntu 16.04上安装OrientDB

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


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

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

关键词: 探索发现

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

网友点评
自媒体专栏

评论

热度

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