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

转载 2015年11月18日 14:57:35
假设我们在 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操作类的)

有好几个等待和唤醒函数,大家可以慢慢试。

Linux 进程控制——等待队列详解

一、什么是睡眠     对于一个进程"睡眠"意味着什么? 当一个进程被置为睡眠, 它被标识为处于一个特殊的状态并且从调度器的运行队列中去除. 直到发生某些事情改变了那个状态, 这个进程将不被在任何 ...
  • lizuobin2
  • lizuobin2
  • 2016年06月29日 21:48
  • 3493

Linux进程的睡眠和唤醒(一个定时信号唤醒睡眠中的进程)

突然想到Nginx中时间更新这块处理,Nginx中为了减少调用系统调用gettimeofday这个函数(因为一旦调用了系统调用,就会使得进程从用户态切换到内核态,就会发生上下文切换,这个代价很大且不值...
  • yusiguyuan
  • yusiguyuan
  • 2015年08月20日 11:35
  • 4677

Linux内核:工作队列

在我的上一篇文章Linux内核:中断、软中断、tasklet中,我们已经了解了中断底半部的两种实现方式,即软中断和tasklet微线程。但是这两种方式归根结底都是采用软中断机制的,其根本上还是在中断的...
  • JansonZhe
  • JansonZhe
  • 2015年10月02日 10:26
  • 1703

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

阅读vhost的时候,发现使用了大量的等待队列和poll,这里温故而知新一下。注:wait_queue_t是等待在wait_queue_head_t队列中的等待元素当你在用户空间需要读写一大片数据的时...
  • leoufung
  • leoufung
  • 2015年09月28日 09:56
  • 362

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

以下来自:http://www.yuanma.org/data/2006/1207/article_1916.htm 假设我们在 kernel 里产生一个 buffer,user 可以经由read,...
  • eric_zl_zhang
  • eric_zl_zhang
  • 2011年10月21日 10:45
  • 519

等待队列wait_queue_head_t使用方法

当你在用户空间需要读写一大片数据的时候,这个就用上了。   以下来自:http://www.yuanma.org/data/2006/1207/article_1916.htm 假设...
  • suwenqiang2011
  • suwenqiang2011
  • 2013年04月23日 09:57
  • 764

等待队列wait_queue_head_t使用

当你在用户空间需要读写一大片数据的时候,这个就用上了。 以下来自:http://www.yuanma.org/data/2006/1207/article_1916.htm 假设我们在 k...
  • huanny2005
  • huanny2005
  • 2015年02月08日 15:20
  • 203

31 completion完成量,wait_queue_head_t等待队列和epoll

完成量, 功能与信号量差不多, 最大不同可以唤醒多个休眠的进程或线程#include struct completion { unsigned int done; //done表示资源,上锁...
  • jklinux
  • jklinux
  • 2017年06月13日 10:50
  • 443

Linux等待队列wait_queue_head_t和wait_queue_t

Linux等待队列wait_queue_head_t和wait_queue_t
  • im1020110542
  • im1020110542
  • 2015年08月18日 19:48
  • 330

linux等待队列wait_queue_head_t和wait_queue_t

等待队列在linux内核中有着举足轻重的作用,很多linux驱动都或多或少涉及到了等待队列。因此,对于linux内核及驱动开发者来说,掌握等待队列是必须课之一。 Linux内核的等待队列是以双循环链表...
  • wh8_2011
  • wh8_2011
  • 2016年07月21日 11:55
  • 200
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux内核的 等待队列 使用方法,wait_queue_head_t,进程休眠
举报原因:
原因补充:

(最多只允许输入30个字)