Linux设备驱动模板:等待队列

我们为什么要用等待队列?

假设我们在 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()了。

结构图:

                               task_struct             task_struct                                 |---------|<--+         |---------|<--+                                 |         |   |         |         |   |                                 |         |   |         |         |   |                                 |         |   |         |         |   |                                 |---------|   |         |---------|   |                                               |                       |                             wait_queue_t      |     wait_queue_t      |                           |---------------|   |   |---------------|   |   wait_queue_head_t       |    flags      |   |   |    flags      |   |   |---------------|       |    *task      |---+   |    *task      |---+   |     lock      |       |    func       |       |    func       |   |---------------|       |---------------|       |---------------|   |list_head *next|------>|list_head *next|------>|list_head *next|   |list_head *prev|<------|list_head *prev|<------|list_head *prev|   |---------------|       |---------------|       |---------------|  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwgsgs.html