http://i.cnblogs.com/EditPosts.aspx?opt=1
 
Two states are associated with sleeping, TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE. They differ only in that tasks in the TASK_UNINTERRUPTIBLE state ignore signals, whereas tasks in the TASK_INTERRUPTIBLE state wake up prematurely and respond to a signal if one is issued. Both types of sleeping tasks sit on a wait queue, waiting for an event to occur, and are not runnable.
    休眠有两种相关的进程状态:TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE。它们的惟一却不是处于TASK_UNINTERRUPTIBLE状态的进程会忽略信号,而处于TASK_INTERRUPTIBLE状态的进程如果收到信号会被唤醒并处理信号(然后再次进入等待睡眠状态)。两种状态的进程位于同一个等待队列上,等待某些事件,不能够运行。
    
因为等待事件而进入睡眠状态的方法:
    the recommended method for sleeping in the kernel is a bit more complicated. 
    在内核中进行休眠的推荐操作相对复杂一些.
The task performs the following steps to add itself to a wait queue: 
进程通过执行下面几步将自己加入到一个等待队列中:
1. Creates a wait queue entry via DECLARE_WAITQUEUE().调用DECLARE_WAITQUEUE()创建一个等待队列的项
|--------------------------------------------------------|
|/* 'q' is the wait queue we wish to sleep on */ |
|DECLARE_WAITQUEUE(wait, current);            |
|--------------------------------------------------------|
 
2. Adds itself to a wait queue via add_wait_queue(). This wait queue awakens the process when the condition for which it is waiting occurs. Of course, there needs to be code elsewhere that calls wake_up() on the queue when the event actually does occur.调用add_wait_queue()把自己加入到队列中。该队列在进程等待的条件满足时唤醒它。当然我们必须在其他地方撰写相关代码,在事件发生时,对等待队列执行wake_up()操作
|--------------------------------------------------------|
|add_wait_queue(q, &wait);                             |
|--------------------------------------------------------|
while (!condition) {     /* condition is the event that we are waiting for */ 
3. Changes the process state to TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE.将进程的状态变更为TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE
|--------------------------------------------------------|
|       /* or TASK_UNINTERRUPTIBLE */            |
|    set_current_state(TASK_INTERRUPTIBLE); |
|--------------------------------------------------------|
4. If the state is set to TASK_INTERRUPTIBLE, a signal wakes the process up. This is called a spurious wake up (a wake-up not caused by the occurrence of the event). So check and handle signals.如果状态被设置为TASK_INTERRUPTIBLE,则信号可以唤醒进程(信号和事件都可以唤醒该进程)。这就是所谓的伪唤醒(唤醒不是因为事件的发生,而是由信号唤醒的),因此检查并处理信号。注: 信号和等待事件都可以唤醒处于 TASK_INTERRUPTIBLE 状态的进程,信号唤醒该进程为伪唤醒; 该进程被唤醒后,如果 (!condition) 结果为真,则说明该进程不是由等待事件唤醒的, 而是由信号唤醒的。 所以该进程处理信号后将再次让出CPU控制权
|--------------------------------------------------------|
|       if (signal_pending(current))                      |
|               /* handle signal */                           |
|--------------------------------------------------------|
5. Tests whether the condition is true. If it is, there is no need to sleep. If it is not true, the task calls schedule().本进程在此处交出CPU控制权,如果该进程再次被唤醒,将从while循环结尾处继续执行,因而将回到while循环的开始处while (!condition),进测等待事件是否真正发生.
|--------------------------------------------------------|
|       schedule();                                             |
|--------------------------------------------------------|
6. Now that the condition is true, the task can set itself to TASK_RUNNING and remove itself from the wait queue via remove_wait_queue().
|--------------------------------------------------------|
|set_current_state(TASK_RUNNING);              |
|remove_wait_queue(q, &wait);                     |
|--------------------------------------------------------|
    If the condition occurs before the task goes to sleep, the loop terminates, and the task does not erroneously go to sleep. Note that kernel code often has to perform various other tasks in the body of the loop. For example, it might need to release locks before calling schedule() and reacquire them after or react to other events. 
    如果在进程开始睡眠之前条件就已经达成了,那么循环会退出,进程不会存在错误的进入休眠的倾向。需要注意的是,内核代码在循环体内常常需要完成一些其他的任务,比如,它可能在调用schedule()之前需要释放掉锁,而在这以后再重新获取它们,或者响应其他的事件。
    Waking is handled via wake_up(), which wakes up all the tasks waiting on the given wait queue. It calls try_to_wake_up(), which sets the task's state to TASK_RUNNING, calls activate_task() to add the task to a runqueue, and sets need_resched if the awakened task's priority is higher than the priority of the current task. The code that causes the event to occur typically calls wake_up() afterward. 
    唤醒操作通过函数wake_up进行,它会唤醒指定的等待队列上的所有进程。它调用函数try_to_wake_up,该函数负责将进程设置为TASK_RUNNING状态,调用activate_task将此进程放入可执行队列,如果被唤醒的进程优先级比当前正在运行的进程的优先级高,还有设置need_resched标志。通常哪段代码促使等待条件达成,它就负责随后调用wake_up()函数。 
    An important note about sleeping is that there are spurious wake-ups. Just because a task is awakened does not mean that the event for which the task is waiting has occurred; sleeping should always be handled in a loop that ensures that the condition for which the task is waiting has indeed occurred. 
    关于休眠有一点需要注意,存在虚假的唤醒。有时候进程被唤醒并不是因为它所等待的条件达成了(而是接受到了信号),所以才需要用一个循环处理来保证它等待的条件真正达成。

睡眠--TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE的更多相关文章

  1. TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE

    TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE 的区别 TASK_INTERRUPT ...

  2. Linux进程的睡眠和唤醒简析

    COPY FROM:http://www.2cto.com/os/201204/127771.html 1 Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在 ...

  3. linux 内核睡眠与唤醒

    休眠(被阻塞)的进程处于一个特殊的不可执行状态.进程休眠由多种原因,但肯定都是为了等待一些事件.事件可能是一 段时间从文件I/O读取更多数据,或者是某个硬件事件.一个进程还由可能在尝试获取一个已被占用 ...

  4. Socket层实现系列 — 睡眠驱动的同步等待

    主要内容:Socket的同步等待机制,connect和accept等待的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 概述 socket上定义了 ...

  5. Linux进程的睡眠和唤醒

    1   Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状态标志位为TASK_RUNNING.一旦一个运行中的进程时间片用完, ...

  6. linux一个进程如何睡眠

    如果我们深入 <linux/wait.h>, 你见到在 wait_queue_head_t 类型后面的数据结构是非 常简单的; 它包含一个自旋锁和一个链表. 这个链表是一个等待队列入口, ...

  7. android开发读书笔记

    第九章心得: HAL ( Hardware Abstraction Layer,硬件抽象腔,〉是建立在Linux驱动之上的一套翻字库.这套程序 j率并不属于 Linux 内核, 而是属于 Linux ...

  8. 《Linux内核分析》之第四章读书笔记

    4.1多任务 多任务操作系统:同时并发地交互执行多个进程的操作系统 多任务操作系统会使多个进程处于堵塞或者睡眠状态.这些任务尽管位于内存,但是并不处于可运行状态.这些进程利用内核堵塞自己,直到某一事件 ...

  9. 20135202闫佳歆--week 8 课本第4章学习笔记

    第四章 进程调度 一.多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于可运行状态. ...

随机推荐

  1. 屏蔽ubuntu桌面鼠标右键以及Ctrl Alt F*

    1.屏蔽右键: xmodmap -e "pointer = 1 2 99"xmodmap -e 'pointer = 1 2 0 4 5 6 7 8 9' #xmodmap -e ...

  2. .net 将excel转成html文件

    最近在做一个打印预览功能,但是开始没有头绪后来用excel做了一个模板,然后根据excel模板来生成新的excel并将其存储为html,可以通过http请求在浏览器中读取,并且打印,其他的不多说.方法 ...

  3. React-router 要点

    1.关于url中传参的问题 比如我想打开: /articles/detail/101 在url中要传一个参数 /articles/detail/:articleId 路由中:<Route pat ...

  4. Implement Custom Cache Dependencies in ASP.NET 1.x

    Code download available at:CuttingEdge0407.exe(128 KB)   Contents What's a Cache Dependency, Anyway? ...

  5. PHP实现中文简体字和繁体字互转

    function convert($str, $action='S'){ if($action != 'S' && $action != 'T'){ return $str; } $s ...

  6. Vb.Net Xml文档格式化

    最近在处理Webservice文档的时候,因为是未格式化的,需要处理,所以有了以下代码. #Region "Xml字符串转换成格式化的XML文件" 'txt_Result.Text ...

  7. LeetCode之Single Number以及拓展

    Problem 1:一个数组中有一个数字a只出现一次,其他数字都出现了两次.请找出这个只出现一次的数字? 考察知识点:异或运算 思路:比如数字 b^b = 0     a^0 = a 因此,可以将数组 ...

  8. Python数据结构——二叉树的实现

    1. 二叉树 二叉树(binary tree)中的每个节点都不能有多于两个的儿子. 1.1 二叉树列表实现 如上图的二叉树可用列表表示: tree=['A', #root ['B', #左子树 ['D ...

  9. 【非原】c语言之声明和定义的区别

    原创地址:http://www.cnblogs.com/haore147/p/3647466.html 什么是定义?什么是声明?它们有何区别? 举个例子: 1 2 A)int i; B)extern  ...

  10. WP8.1和Win8.1的不同之处

    本文仅是个人见解,如有不足或错误之处欢迎批评指正~ 1.Toast: 创建Toast代码差不多但实现机制及管理上不一样 2.ApplicationData: WP8.1多了一个LocalCacheFo ...