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.
关于休眠有一点需要注意,存在虚假的唤醒。有时候进程被唤醒并不是因为它所等待的条件达成了(而是接受到了信号),所以才需要用一个循环处理来保证它等待的条件真正达成。
[b]本文来自ChinaUnix博客,如果查看原文请点:http://www.cnblogs.com/parrynee/archive/2010/01/14/1648165.html
相关推荐
- **TASK_UNINTERRUPTIBLE**:不可中断的睡眠状态,不会因信号而唤醒。 - **TASK_ZOMBIE**:僵尸状态,进程已经结束但其父进程尚未读取其退出状态。 - **TASK_STOPPED**:停止状态,进程已暂停。 - **TASK_TRACED**...
- volatile long state:描述进程的状态,有多个可能的值,如TASK_RUNNING表示正在运行,TASK_INTERRUPTIBLE表示进程可以被信号唤醒的睡眠状态,TASK_UNINTERRUPTIBLE表示进程处于不可中断的睡眠状态, TASK_ZOMBIE...
3. **TASK_UNINTERRUPTIBLE(不可中断阻塞状态)**:与`TASK_INTERRUPTIBLE`类似,但在等待期间不能被任何信号或定时中断唤醒,直到所需资源可用为止。 4. **TASK_STOPPED(停止状态)**:进程被停止,通常是因为...
以及统计系统中进程个数,包括统计系统中 TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE、TASK_STOPPED 等(还有其他状态)状态进程的个数。同时还需要编写一个用户态下执行的程序,格式化...
进程状态有多种,例如TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE、TASK_STOPPED和TASK_SWAPPING。其中,TASK_RUNNING表示进程正在运行或者在就绪队列中等待运行;TASK_INTERRUPTIBLE和...
- **TASK_UNINTERRUPTIBLE**:不可中断的睡眠状态。 - **TASK_STOPPED** 和 **TASK_TRACED**:分别表示进程被暂停和正在被跟踪的状态。 - **EXIT_ZOMBIE** 和 **EXIT_DEAD**:进程已退出但未被清理的状态,其中 EXIT...
Linux进程的状态分为五类:`TASK_RUNNING`、`TASK_INTERRUPTIBLE`、`TASK_UNINTERRUPTIBLE`、`TASK_STOPPED`和`TASK_ZOMBIE`。`TASK_RUNNING`表示进程可以运行,无论是正在占用CPU还是等待运行。所有的可运行进程被...
`TASK_INTERRUPTIBLE`状态的进程正在睡眠,但接收信号后会变为`TASK_RUNNING`。`TASK_UNINTERRUPTIBLE`状态与前者类似,但无法通过信号唤醒,通常需要调用`wake_up()`函数来激活。 每个进程在Linux内核中由`task_...
在 Linux 操作系统中,每个进程都有其自己的状态,包括 TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_STOPPED、TASK_TRACED 等。其中,TASK_RUNNING 状态表示进程正在运行,TASK_INTERRUPTIBLE ...
1. 进程状态(state):表明进程是正在运行(TASK_RUNNING)、可中断睡眠(TASK_INTERRUPTIBLE)、不可中断睡眠(TASK_UNINTERRUPTIBLE)、暂停(TASK_STOPPED)、僵死(TASK_ZOMBIE)还是正在交换(TASK_SWAPPING)...
1 Linux进程的睡眠和唤醒 ...Linux 中的进程睡眠状态有两种:一种是可中断的睡眠状态,其状态标志位TASK_INTERRUPTIBLE; 另一种是不可中断 的睡眠状态,其状态标志位为TASK_UNINTERRUPTIBLE。可中断
- `TASK_UNINTERRUPTIBLE`:此状态与`TASK_INTERRUPTIBLE`相似,但即使接收到信号也不会唤醒进程。这种状态适用于那些必须无中断等待的情况,或者预期事件很快就会发生。 - 其他状态还包括`TASK_ZOMBIE`(僵尸状态,...
不可中断睡眠状态(TASK_UNINTERRUPTIBLE) 不可中断睡眠状态与可中断睡眠状态类似。但处于该状态的进程只有被使用 wake_up() 函数明确唤醒时才能转换到可运行的就绪状态。 暂停状态(TASK_STOPPED) 暂停状态是...
在Linux内核中,每个进程都有五个状态:TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE和TASK_STOPPED。其中,TASK_RUNNING状态表示进程没有被阻塞,即READY和RUNNING的结合体。TASK_...
task_struct结构体中保存了进程状态,Linux进程有五种状态:运行(TASK_RUNNING)、可中断睡眠(TASK_INTERRUPTIBLE)、不可中断睡眠(TASK_UNINTERRUPTIBLE)、僵尸(TASK_ZOMBIE)和暂停/调试状态(TASK_STOPPED /...
2. 统计系统中不同状态的进程数量,如`TASK_RUNNING`(正在执行的进程)、`TASK_INTERRUPTIBLE`(可中断的睡眠进程)、`TASK_UNINTERRUPTIBLE`(不可中断的睡眠进程)、`TASK_ZOMBIE`(僵尸进程)和`TASK_STOPPED`...
1. **状态转换**:当运行中的进程变为`TASK_INTERRUPTIBLE`、`TASK_UNINTERRUPTIBLE`或`TASK_STOPPED`时,会触发调度。 2. **进程撤销**:进程结束或被终止时,也会执行调度。 3. **时间片耗尽**:每个进程都有一定...
Linux进程有多种状态,如TASK_RUNNING、EXIT_DEAD、TASK_INTERRUPTIBLE等。其中,TASK_UNINTERRUPTIBLE,即D状态,是一种特殊的等待状态,进程中止接收信号,除非通过特定的唤醒操作(如wake_up)才能使其恢复。D...
3. 不可中断阻塞状态(TASK_UNINTERRUPTIBLE):进程无法响应除中断外的任何事件,必须由特定的唤醒函数唤醒。用字符`D`表示。 4. 暂停状态(TASK_STOP/TASK_TRACED):进程收到特定信号后进入此状态,可通过发送`...