来源:http://blog.csdn.net/allen6268198/article/details/8112551

1. 关于 wait_event_interruptible() 和 wake_up()的使用
  
读一下wait_event_interruptible()的源码,不难发现这个函数先将
当前进程的状态设置成TASK_INTERRUPTIBLE,然后调用schedule(),
而schedule()会将位于TASK_INTERRUPTIBLE状态的当前进程从runqueue
队列中删除。从runqueue队列中删除的结果是,当前这个进程将不再参
与调度,除非通过其他函数将这个进程重新放入这个runqueue队列中,
这就是wake_up()的作用了。
  
由于这一段代码位于一个由condition控制的for(;;)循环中,所以当由
shedule()返回时(当然是被wake_up之后,通过其他进程的schedule()而
再次调度本进程),如果条件condition不满足,本进程将自动再次被设
置为TASK_INTERRUPTIBLE状态,接下来执行schedule()的结果是再次被
从runqueue队列中删除。这时候就需要再次通过wake_up重新添加到
runqueue队列中。
  
如此反复,直到condition为真的时候被wake_up.
  
可见,成功地唤醒一个被wait_event_interruptible()的进程,需要满足:
  
   在 1)condition为真的前提下,2) 调用wake_up()。

所以,如果你仅仅修改condition,那么只是满足其中一个条件,这个时候,
被wait_event_interruptible()起来的进程尚未位于runqueue队列中,因
此不会被 schedule。这个时候只要wake_up一下就立刻会重新进入运行调度。
  
2. 关于wait_event_interruptible的返回值
  
根据 wait_event_interruptible 的宏定义知:
  
   1) 条件condition为真时调用这个函数将直接返回0,而当前进程不会
      被 wait_event_interruptible和从runqueue队列中删除。
  
   2) 如果要被wait_event_interruptible的当前进程有nonblocked pending
      signals, 那么会直接返回-ERESTARTSYS(i.e. -512),当前进程不会
      被wait_event_interruptible 和从runqueue队列中删除。
  
   3) 其他情况下,当前进程会被正常的wait_event_interruptible,并从
      runqueue队列中删除,进入TASK_INTERRUPTIBLE状态退出运行调度,
      直到再次被唤醒加入runqueue队列中后而参与调度,将正常返回0。
  
附1:wait_event_interruptible  宏
  
#define wait_event_interruptible(wq, condition)    \
({                                                 \
     int __ret = 0;                                  \
     if (!(condition))                               \
      __wait_event_interruptible(wq, condition, __ret); \
      __ret;                                         \
})
  
注: C语言中{a,b, ..., x}的的值等于最后一项,即x,因此上述
宏的值是 __ret。
  
  
附2:wait_event_interruptible()和 wake_up的等效代码
  
wait_event_interruptible(wq, condition) /*等效没有考虑返回值*/
{
     if (!(condition))
     {
         wait_queue_t _ _wait;
         init_waitqueue_entry(&_ _wait, current);
         add_wait_queue(&wq, &_ _wait);
         for (;;)
         {
            set_current_state(TASK_INTERRUPTIBLE);
            if (condition)
            break;
            schedule();  /* implicit call: del_from_runqueue(current)*/
         }
         current->state = TASK_RUNNING;
         remove_wait_queue(&wq, &_ _wait);
      }
}
  
  
void wake_up(wait_queue_head_t *q)
{
      struct list_head *tmp;
      wait_queue_t *curr;
      list_for_each(tmp, &q->task_list)
      {
        curr = list_entry(tmp, wait_queue_t, task_list);
        wake_up_process(curr->task);
        /* implicit call: add_to_runqueue(curr->task);*/
        if (curr->flags)
          break;
      }
}

关于 wait_event_interruptible() 和 wake_up()的使用的更多相关文章

  1. Linux学习 :中断处理机制 & poll机制

    中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务 的程序中去,服务完毕后再返回去继续运行被暂时中断的程序 ...

  2. 【Linux驱动】内核等待队列

    在Linux中, 一个等待队列由一个"等待队列头"来管理,等待队列是双向链表结构. 应用场合:将等待同一资源的进程挂在同一个等待队列中. 数据结构 在include/linux/w ...

  3. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

  4. I/O多路复用 SELECT POLL -- 内核实现

    等待队列 先补充个基础知识――等待队列 认识 定义 wait_queue_head_t wait_queue; 初始化 init_waitqueue_head(&wait_queue); 等待 ...

  5. FL2440驱动添加(5)ADC驱动学习笔记

    由图可知,模拟ADC分为两部分功能,一部分是触屏功能,另一部分就是普通ADC功能.分别可以产生INT_TC和INT_ADC 两个中断.该ADC模块总共有8个通道可以进行模拟信号的输入,分别是AIN0. ...

  6. linux设备驱动归纳总结(七):1.时间管理与内核延时【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxx ...

  7. linux设备驱动归纳总结(三):5.阻塞型IO实现【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-60025.html linux设备驱动归纳总结(三):5.阻塞型IO实现 xxxxxxxxxxxxxx ...

  8. rtc关机闹钟7 jni层 com_android_server_AlarmManagerService

    frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp int AlarmImplAlarmDrive ...

  9. Linux驱动设计——阻塞和同步

    阻塞和非阻塞是设备访问的两种基本方式,阻塞和非阻塞驱动程序使用时,经常会用到等待队列. 阻塞和非阻塞 阻塞操作是指在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作.被挂起的 ...

随机推荐

  1. Mac下Intellij IDea发布Web项目详解一

    Mac下Intellij IDea发布Web项目详解一 Mac下Intellij IDea发布Java Web项目(适合第一次配置Tomcat的家伙们)详解二 Mac下Intellij IDea发布J ...

  2. 【模拟赛】BYVoid魔兽世界模拟赛 解题报告

    题目名称(点击进入相关题解) 血色先锋军 灵魂分流药剂 地铁重组 埃雷萨拉斯寻宝 源文件名(.c/.cpp/.pas) scarlet soultap subway eldrethalas 输入文件名 ...

  3. angularJS 指令一

    指令1.指令本质上就是AngularJS拓展具有自定义功能的HTML元素的途径.通过自定义元素来创建指令,如:<my-directive></my-directive>.dir ...

  4. SCOI2015酱油记

    Orz怒跪ns高一进A队,常规还是年级rank1,把gerw都下了一跳. Day1还是拿了点分的,调了半天T3终于调出来了(果然xlk大神可信),加上T1暴力有120(跟爆蛋有什么区别).T1大概有2 ...

  5. android控件上面实现提醒信息

    android开发中,经常会用到显示一个提醒信息,比如个人中心,有新信息,购买商品后,在购物车控件,显示购物数量等.我们可以用,2个控件来实现,或者用层叠图. 还有一种简单方便的办法,使用别人的开源代 ...

  6. MYSQL 体系结构图-LRU

  7. 关于 java.util.concurrent 您不知道的 5 件事--转

    第 1 部分 http://www.ibm.com/developerworks/cn/java/j-5things4.html Concurrent Collections 是 Java™ 5 的巨 ...

  8. Gradle学习目录总结

    如果是你想干的事情,在别人看起来可能是很难的一件事,不过你自己很喜欢,你不会觉得很苦.我开始创业那会是28岁.对我来讲,我创业的目的不是为了自己当老板,我希望有一个平台有一个环境,我可以控制一些资源, ...

  9. vim 设定一个新的snippets

    目录 ~/.vim/bundle/vim-snippets/snippets 编辑 _.snippets 在最后添加一行自己需要的,比如想要个自己的名字,然后按tab,即出现全称,可以添加如下内容 s ...

  10. 初识Ajax技术

    Ajax:(Asynchronous JavaScript And Xml)是一种整合了JavaScript.XML.CSS等现有技术 Ajax工作流程:   纯javaScript的Ajax请求   ...