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

Linux内核等待队列机制介绍(转载)

2007-01-23 22:18 281 查看
相信很多写程序的人都写过 socket 的程序。当我们 open 一个 socket 之后,接着去
读取这个 socket,如果此时没有任何资料可供读取,那 read 就会 block 住。(这是
没有加上 O_NONBLOCK 的情形),直到有资料可读取才会传回来。在 Linux kernel 里
有一个数据结构可以帮助我们做到这样的功能。这个数据结构就是这里要跟各位介绍的
wait queue。在 kernel 里,wait_queue 的应用很广,举凡 device driver
semaphore 等方面都会使用到 wait_queue 来 implement。所以,它算是 kernel 里蛮
基本的一个数据结构。

接下来,我要跟各位介绍一下 wait_queue 的用法,以及用一个例子来说明如何使用
wait_queue。最后,我会带各位去 trace 一下 wait_queue 的原始程序代码,看看
wait_queue 是如何做到的。

我想有件事要先提及的是 Linux 在 user space 跟在 kernel space 上的差异。我们
知道 Linux 是 multi-tasking 的环境,同时可以有很多人执行很多的程序。这是从
user 的观点来看的。如果就 kernel 的观点来看,是没有所谓的 multi-tasking 的。
在 kernel 里,只有 single-thread。也就是说,如果你的 kernel code 正在执行,
那系统里只有那部分在执行。不会有另一部分的 kernel code 也在运作。当然,这是
指 single processor 的情况下,如果是 SMP 的话,那我就不清楚了。我想很多人都
在 Windows 3.1 下写过程序,在那种环境下写程序,每一个程序都必须适当的将 CPU
让给别的程序使用。如果有个程序里面有一个

while (1);

的话,那保证系统就停在那里了。这种的多任务叫做 non-preemptive。它多任务的特
性是由各个程序相互合作而造成的。在 Linux 的 user space 下,则是所谓的
preemptive,各个 process 喜欢执行什么就执行什么,就算你在你的程序里加上
while(1); 这一行也不会影响系统的运作。反正时间到了,系统自动就会将你的程序停
住,让别的程序去执行。这是在 user space 的情况下,在 kernel 这方面,就跟
Windows 3.1 程序是一样的。在 kernel 里,你必须适当的将 CPU 的执行权释放出
来。如果你在 kernel里加入 while(1); 这一行。那系统就会跟 Windows 3.1 一样。
卡在那里。当然啦,我是没试过这样去改 kernel,有兴趣的人可以去试试看,如果有
不同的结果,请记得告诉我。

假设我们在 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
可以运作,那系统就不会当。这是一个方式。但是,如果我们使用 wait_queue 的话,
那程序看起来会比较漂亮,而且也比较让人了解,如下所示:

struct wait_queue *wq = NULL; /* global variable */
while ( is_full )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: