您的位置:首页 > 运维架构 > Linux

linux内核的 等待队列 使用方法,wait_queue_head_t,进程休眠

2009-11-05 09:18 756 查看
当你在用户空间需要读写一大片数据的时候,这个就用上了。



以下来自:http://www.yuanma.org/data/2006/1207/article_1916.htm

假设我们在 kernel 里产生一个 buffer,user 可以经由
read,write 等 system call 来读取或写资料到这个 buffer 里。如果有一个 user 写资料到 buffer
时,此时 buffer 已经满了。那请问你要如何去处理这种情形呢 ? 第一种,传给 user 一个错误讯息,说 buffer
已经满了,不能再写入。第二种,将 user 的要求 block 住, 等有人将 buffer 内容读走,留出空位时,再让 user
写入资料。但问题来了,你要怎么将 user 的要求 block 住。难道你要用
while ( is_full );
write_to_buffer;
这样的程序代码吗? 想想看,如果你这样做会发生什么事?
第一,kernel会一直在这个 while 里执行。第二个,如果 kernel 一直在这个 while 里执行,表示它没有办法去
maintain系统的运作。那此时系统就相当于当掉了。在这里 is_full 是一个变量,当然,你可以让 is_full 是一个
function,在这个 function里会去做别的事让 kernel
可以运作,那系统就不会当。这是一个方式。还有,你说可以在while里面把buffer里的内容读走,再把is_full的值改了,但是我们会可能把重
要的数据在我们不想被读的时候被读走了,那是比较麻烦的,而且很不灵活.如果我们使用 wait_queue 的话,
那程序看起来会比较漂亮,而且也比较让人了解,如下所示:

struct wait_queue_head_t wq; /* global variable */
DECLARE_WAIT_QUEUE_HEAD (wq);

while ( is_full ){
interruptible_sleep_on( &wq );
} write_to_buffer();


interruptible_sleep_on( &wq )
是用来将目前的 process,也就是要求写资料到buffer 的 process放到 wq 这个 wait_queue 里。在
interruptible_sleep_on 里,则是最后会呼叫 schedule() 来做 schedule
的动作,谁调用了schedule谁就趴下,让别人去运行,醒来就原地起来,执行schedule()后的代码。那那个调用了schedule的家伙什么
醒过来呢?这时候就需要用到另一个函数了wake_up_interruptible()了。



以下来自:http://tauruspdj.blog.163.com/blog/static/4312500620090794030998/

linux中最简单的休眠方式是下面的宏,

wait_event(queue, condition)
/*
进程将被置于非中断休眠(uninterruptible sleep)*/

wait_event_interruptible(queue, condition)
/*进程可被信号中断休眠,返回非0值表示休眠被信号中断*/

wait_event_timeout(queue, condition, timeout) /*等待限定时间jiffy,condition满足其一返回0*/

wait_event_interruptible_timeout(queue, condition, timeout)

queue是等待队列头,传值方式

condition是任意一个布尔表达式,在休眠前后多次对condition求值,为真则唤醒

唤醒进程的基本函数是wake_up

void wake_up(wait_queue_head_t *queue);
/*唤醒等待在给定queue上的所有进程*/

void wake_up_interruptible(wait_queue_head_t *queue);

实践中,一般是wait_event和
wake_up,
wait_event_interruptible和
wake_up_interruptible
成对使用。



【补充】其实看了那么多,他们也没有给个立即可用的步骤,写blog嘛,就是分享心得。我基于2.6.24总结一下,希望对大家有帮助:

1、定义:wait_queue_head_t my_queue;

2、初始化 init_waitqueue_head(&my_queue);

3、在一个函数里面等待:wait_event(queue, condition) ;(别在中断里面搞)

4、在另一个函数里面唤醒:wake_up(wait_queue_head_t *queue); (这个可以在中断调用,去唤醒别的进程,特别是dma操作类的)

有好几个等待和唤醒函数,大家可以慢慢试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: