扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
相信很多写程序的人都写过 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 的话,那程序看起来会比较漂亮,而且也比较让人了解,如下所示:
|
interruptible_sleep_on( &wq ) 是用来将目前的 process,也就是要求写资料到 buffer 的 process放到 wq 这个 wait_queue 里。在 interruptible_sleep_on 里,则是最后会呼叫 schedule() 来做 schedule 的动作,也就是去找另一个 process 来执行以维持系统的运作。当执行完 interruptible_sleep_on 之后,要求 write 的 process 就会被 block 住。那什么时候会恢复执行呢 ? 这个 process 之所以会被 block 住是因为 buffer 的空间满了,无法写入。但是如果有人将 buffer 的资料读取掉,则 buffer 就有空间可以让人写入。所以,有关于叫醒 process 的动作应该是在 read buffer 这方面的程序代码做的。
|
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者