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

内核等待队列机制介绍

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

于它们的程序代码有没有更改就不太清楚了。至于到那一版才改的。我没有仔细去查,只知道在 2.0.36 时还没改,到了 2.2.1 就改了。这两个 function 是 macro,都定义在 里。要使用前记得先 include 进来。

相信 buf_read() 的程序代码应当不难了解才对。不知道各位有没有看到,在buf_read() 的后面有一行的程序,就是

wake_up_interruptible( write_wq );

write_wq 是我们用来放那些想要写资料到 buffer,但 buffer 已满的 process。这一行的程序会将挂在此 queue 上的 process 叫醒。当 queue 是空的时,也就是当 write_wq 为 NULL 时,wake_up_interruptible() 并不会造成任何的错误。接下来,我们来看看更改后的 buf_write()。

static ssize_t buf_write( struct file *filp,const char *buf,size_t count,loff_t *ppos )
{
int num,nWrite;
nWrite = 0;
while ( ( wp == rp ) flag ) {
interruptible_sleep_on( write_wq );
}

repeate_writing:
if ( rp > wp ) {
num = min( count,( int ) ( rp - wp ) );
}
else {
num = min( count,( int ) ( buffer BUF_LEN - wp ) );
}
copy_from_user( wp,buf,num );
wp = num;
count -= num;
nWrite = num;
if ( wp == ( buffer BUF_LEN ) ) {
wp = buffer;
}
if ( ( wp != rp ) ( count > 0 ) ) {
goto repeate_writing;
}
flag = 1;
return nWrite;
}

我们把 process 丢到 write_wq 的动作放在 buf_write() 里。当 buffer 已满时,就直接将 process 丢到 write_wq 里.

while ( ( wp == rp ) flag ) {
interruptible_sleep_on( write_wq );
}

好了。现在程序已经做了一些修改。再重新 make 一次,利用 insmod 将 buf.o 载到 kernel 里就行了。接着,我们就来试验一下是不是真正做到 block IO.

# cd /dev
# ls -l ~/WWW-HOWTO
-rw-r--r-- 1 root root 23910 Apr 14 16:50 /root/WWW-HOWTO
# cat ~/WWW-HOWTO > buf

执行到这里,应该会被 block 住。现在,我们再开一个 shell 出来.

# cd /dev
# cat buf
..。( contents of WWW-HOWTO ) ..。skip ...

此时,WWW-HOWTO 的内容就会出现了。而且之前 block 住的 shell 也已经回来了。最后,试验结束,可以下

# rmmod buf

将 buf 这个 module 从 kernel 中移除。以上跟各位介绍的就是 wait_queue 的使用。希望能对各位有所助益。

我想对某些人来讲,会使用一个东西就够了。然而对某些人来讲,可能也很希望知道这项东西是如何做出来的。至少我就是这种人。在下面,我将为各位介绍 wait_queue 的 implementation。如果对其 implementation 没兴趣,以下这一段就可以略过不用看了。

wait_queue 是定义在 里,我们可以先看看它的数据结构是怎么样:

struct wait_queue {
struct task_struct * task;
struct wait_queue * next;
};

很简单是吧。这个结构里面只有二个字段,一个是 task_struct 的 pointer,另一个则是 wait_queue 的 pointer。很明显的,我们可以看出 wait_queue 其实就是一个 linked list,而且它还是一个 circular linked list。 其中 task_struct 就是用来指呼叫 sleep_on 等 function的 process。在 Linux 里,每一个 process 是由一个 task_struct 来描叙。task_struct 是一个很大的的结构,在此我们不会讨论。Linux 里有一个 global variable,叫 current,它会指到目前正在执行的 process 的 task_struct 结构。这也就是为什么当 process 呼叫 system call,切换到 kernel 时,kernel 会知道是那个 process 呼叫的。

好,我们现在来看看 interruptible_sleep_on() 和 sleep_on() 是如何做的。这两个 function 都是位于 /usr/src/linux/kernel/sched.c 里。

void interruptible_sleep_on(struct wait_queue **p)
{
SLEEP_ON_VAR
current->state = TASK_INTERRUPTIBLE;
SLEEP_ON_HEAD
schedule();
SLEEP_ON_TAIL
}

void sleep_on(struct wait_queue **p)
{
SLEEP_ON_VAR
current->state = TASK_UNINTERRUPTIBLE;
SLEEP_ON_HEAD
schedule();
SLEEP_ON_TAIL
}

各位有没有发现这两个 function 很类似。是的,它们唯一的差别就在于

current->state = ...

这一行而已。之前,我们有说过,interruptible_sleep_on() 可以被 signal 中断,所以,其 current->state 被设为 TASK_INTERRUPTIBLE。而 sleep_on() 没办法被中断,所以 current->state 设为 TASK_UNINTERRUPTIBLE。接下来,我们只看 interruptible_sleep_on() 就好了。毕竟它

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

网站地图

Top