内核中随处可见的等待队列详解3

来源:互联网 发布:windows查看tcp连接数 编辑:程序博客网 时间:2024/05/01 10:34

6、在等待队列上睡眠:

(1)sleep_on()函数:

 

void __sched sleep_on(wait_queue_head_t *q)  {
unsigned long flags;
wait_queue_t wait; init_waitqueue_entry(&wait, current); current->state = TASK_UNINTERRUPTIBLE; sleep_on_head(q, &wait, &flags);
schedule();
sleep_on_tail(q, &wait, &flags);
}

 

该函数的作用是定义一个等待队列(wait),并将当前进程添加到等待队列中(wait),然后将当前进程的状态置为TASK_UNINTERRUPTIBLE,并将等待队列(wait)添加到等待队列头(q)中。之后就被挂起直到资源可以获取,才被从等待队列头(q)中唤醒,从等待队列头中移出。在被挂起等待资源期间,该进程不能被信号唤醒。

(2)sleep_on_timeout()函数:

 

long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
unsigned long flags;
wait_queue_t wait
init_waitqueue_entry(&wait, current); current->state = TASK_UNINTERRUPTIBLE;
sleep_on_head(q, &wait, &flags);
timeout = schedule_timeout(timeout);
sleep_on_tail(q, &wait, &flags);
return timeout;
}

 

sleep_on()函数的区别在于调用该函数时,如果在指定的时间内(timeout)没有获得等待的资源就会返回。实际上是调用schedule_timeout()函数实现的。值得注意的是如果所给的睡眠时间(timeout)小于0,则不会睡眠。该函数返回的是真正的睡眠时间。

(3)interruptible_sleep_on()函数:


void __sched interruptible_sleep_on(wait_queue_head_t *q)

{

unsigned long flags;

wait_queue_t wait;

 

init_waitqueue_entry(&wait, current);

 

current->state = TASK_INTERRUPTIBLE;

 

sleep_on_head(q, &wait, &flags);

schedule();

sleep_on_tail(q, &wait, &flags);

}

 

该函数和sleep_on()函数唯一的区别是将当前进程的状态置为TASK_INTERRUPTINLE,这意味在睡眠如果该进程收到信号则会被唤醒。

(4)interruptible_sleep_on_timeout()函数:


long __sched

interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)

{

unsigned long flags;

wait_queue_t wait;

 

init_waitqueue_entry(&wait, current);

 

current->state = TASK_INTERRUPTIBLE;

 

sleep_on_head(q, &wait, &flags);

timeout = schedule_timeout(timeout);

sleep_on_tail(q, &wait, &flags);

 

return timeout;

}

 

类似于sleep_on_timeout()函数。进程在睡眠中可能在等待的时间没有到达就被信号打断而被唤醒,也可能是等待的时间到达而被唤醒。

 

以上四个函数都是让进程在等待队列上睡眠,不过是小有诧异而已。在实际用的过程中,根据需要选择合适的函数使用就是了。例如在对软驱数据的读写中,如果设备没有就绪则调用sleep_on()函数睡眠直到数据可读(可写),在打开串口的时候,如果串口端口处于关闭状态则调用interruptible_sleep_on()函数尝试等待其打开。在声卡驱动中,读取声音数据时,如果没有数据可读,就会等待足够常的时间直到可读取。

 

等待队列应用模式
等待队列的的应用涉及两个进程,假设为A和B。A是资源的消费者,B是资源的生产者。A在消费的时候必须确保资源已经生产出来,为此定义一个资源等待队列。这个队列同时要被进程A和进程B使用,我们可以将它定义为一个全局变量。
DECLARE_WAIT_QUEUE_HEAD(rsc_queue);
在进程A中,执行逻辑如下:
while (resource is unavaiable) {
    interruptible_sleep_on( &wq );
}
consume_resource();
在进程B中,执行逻辑如下:
produce_resource();
wake_up_interruptible( &wq );

转自http://341719xubin.blog.163.com/blog/static/132920793201161935033860/