微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 内核等待队列机制介绍

内核等待队列机制介绍

时间:02-25 来源:互联网 点击:

it_queue 的用法。很简单不是吗? 接下来,我会再介绍一下 wait_queue 提供那些 function 让我们使用。让我再重申一次。wait_queue 应设为 global variable,比方叫 wq,只要任何的 process 想将自己挂在上面,就可以直接叫呼叫 sleep_on 等 function。要将 wq 上的 process 叫醒。只要呼叫 wake_up 等 function 就可以了.

就我所知,wait_queue 提供4个 function 可以使用,两个是用来将 process 加到 wait_queue 的:

sleep_on( struct wait_queue **wq );
interruptible_sleep_on( struct wait_queue **wq );

另外两个则是将process从wait_queue上叫醒的。

wake_up( struct wait_queue **wq );
wake_up_interruptible( struct wait_queue **wq );

我现在来解释一下为什么会有两组。有 interruptible 的那一组是这样子的。当我们去 read 一个没有资料可供读取的 socket 时,process 会 block 在那里。如果我们此时按下 Ctrl C,那 read() 就会传回 EINTR。像这种的 block IO 就是使用 interruptible_sleep_on() 做到的。也就是说,如果你是用 interruptible_sleep_on() 来将 process 放到 wait_queue 时,如果有人送一个 signal 给这个 process,那它就会自动从 wait_queue 中醒来。但是如果你是用 sleep_on() 把 process 放到 wq 中的话,那不管你送任何的 signal 给它,它还是不会理你的。除非你是使用 wake_up() 将它叫醒。sleep 有两组。wake_up 也有两组。wake_up_interruptible() 会将 wq 中使用 interruptible_sleep_on() 的 process 叫醒。至于 wake_up() 则是会将 wq 中所有的 process 叫醒。包括使用 interruptible_sleep_on() 的 process。

在使用 wait_queue 之前有一点需要特别的小心,呼叫 interruptible_sleep_on() 以及 sleep_on() 的 function 必须要是 reentrant。简单的说,reentrant 的意思是说此 function不会改变任何的 global variable,或者是不会 depend on 任何的 global variable,或者是在呼叫 interruptible_sleep_on() 或 sleep_on() 之后不会 depend on 任何的 global variable。因为当此 function 呼叫 sleep_on() 时,目前的 process 会被暂停执行。可能另一个 process 又会呼叫此 function。若之前的 process 将某些 information 存在 global variable,等它恢复执行时要使用,结果第二行程进来了,又把这个 global variable 改掉了。等第一个 process 恢复执行时,放在 global variable 中的 information 都变了。产生的结果恐怕就不是我们所能想象了。其实,从 process 执行指令到此 function 中所呼叫的 function 都应该是要 reentrant 的。不然,很有可能还是会有上述的情形发生.

由于 wait_queue 是 kernel 所提供的,所以,这个例子必须要放到 kernel 里去执行。我使用的这个例子是一个简单的 driver。它会 maintain 一个 buffer,大小是 8192 bytes。提供 read跟 write 的功能。当 buffer 中没有资料时,read() 会马上传回,也就是不做 block IO。而当 write buffer 时,如果呼叫 write() 时,空间已满或写入的资料比 buffer 大时,就会被 block 住,直到有人将 buffer 里的资料读出来为止。在 write buffer 的程序代码中,我们使用 wait_queue 来做到 block IO 的功能。在这里,我会将此 driver 写成 module,方便加载 kernel。

第一步,这个 driver 是一个简单的 character device driver。所以,我们先在 /dev 下产生一个 character device。major number 我们找一个比较没人使用的,像是 54,minor number 就用 0。接着下一个命令.

mknod /dev/buf c 54 0

mknod 是用来产生 special file 的 command。/dev/buf 表示要产生叫 buf 的档案,位于 /dev 下。 c 表示它是一个 character device。54 为其 major number,0 则是它的 minor number。有关 character device driver 的写法。有机会我再跟各位介绍,由于这次是讲 wait_queue,所以,就不再多提 driver 方面的东西.

第二步,我们要写一个 module,底下是这个 module 的程序代码:

buf.c
#define MODULE
#include
#include
#include
#include
#include
#define BUF_LEN 8192

int flag; /* when rp = wp,flag = 0 for empty,flag = 1 for
non-empty */
char *wp,*rp;
char buffer[BUF_LEN];
EXPORT_NO_SYMBOLS; /* don't export anything */

static ssize_t buf_read( struct file *filp,char *buf,size_t count,
loff_t *ppos )
{
return count;
}

static ssize_t b

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top