C语言内核等待队列机制介绍

上传人:cn****1 文档编号:513135195 上传时间:2023-11-12 格式:DOC 页数:31 大小:181.50KB
返回 下载 相关 举报
C语言内核等待队列机制介绍_第1页
第1页 / 共31页
C语言内核等待队列机制介绍_第2页
第2页 / 共31页
C语言内核等待队列机制介绍_第3页
第3页 / 共31页
C语言内核等待队列机制介绍_第4页
第4页 / 共31页
C语言内核等待队列机制介绍_第5页
第5页 / 共31页
点击查看更多>>
资源描述

《C语言内核等待队列机制介绍》由会员分享,可在线阅读,更多相关《C语言内核等待队列机制介绍(31页珍藏版)》请在金锄头文库上搜索。

1、C 语言内核等待队列机制介绍C 语言内核等待队列机制介绍相信很多写程序的人都写过 socket 的程序。当我们 open 一个 socket 之后,接着去读取这个 socket,如果此时没有任何资料可供读取, 那 read就会block住。(这是没有加上O_NONBLOCK的情形),直到有资料可读取才会传回来。在Linux kernel里有一个数据结构可以帮助我们做到这样的功能。这个数据结构就是这里要跟各位介绍的 wait queue。在 kernel 里,wait_queue 的应用很广,举凡 device driver semaphore 等方面都会使用到 wait_queue 来 imp

2、lement 。所以, 它算是 kernel 里蛮基本的一个数据结构。接下来,我要跟各位介绍一下wait_queue的用法,以及用一个例子来说明如何使用wait_queue。最后,我会带各位去trace 一下wait_queue 的原始程序代码,看看 wait_queue 是如何做到的。我想有件事要先提及的是Linux在 user space 跟在kernel space 上的差异。我们知道Linux是 multi-tasking的环境,同时可以有很多人执行很多的程序。这是从user 的观点来看的。如果就kernel 的观点来看,是没有所谓的multi-tasking的。在kernel 里,只

3、有single-thread。也就是说,如果你的 kernel code 正在执行,那系统里只有那部分在执行。 不会有另一部分的 kernel code也在运作。当然,这是指single processor 的情况下,如果是 SMP 的话,那我就不清楚了。我想很多人都在Windows3.1 下写过程序,在那种环境下写程序,每一个程序都必须适当的将CPU 让给别的程序使用。如果有个程序里面有一个 while (1); 的话,那保证系统就停在那里了。这种的多任务叫做 non-preemptive 。它多任务的特性是由各个程序相互合作而造成的。在 Linux 的 user space 下,则是所谓的

4、preemptive,各个process 喜欢执行什么就执行什么,就算你在你的程序里加上while(1); 这一行也不会影响系统的运作。反正时间到了,系统自动就会将你的程序停住,让别的程序去执行。这是在user space 的情况下,在 kernel 这方面,就跟Windows 3.1 程序是一样的。在 kernel里,你必须适当的将CPU 的执行权释放出来。 如果你在 kernel 里加入 while(1); 这一行。那系统就会跟Windows 3.1一样。卡在那里。当然啦,我是没试过这样去改kernel,有兴趣的人可以去试试看,如果有不同的结果,请记得告诉我。假设我们在 kernel 里产

5、生一个 buffer ,user 可以经由read,write等 system call 来读取或写资料到这个buffer 里。如果有一个 user 写资料到 buffer 时,此时 buffer 已经满了。那请问你要如何去处理这种情形呢? 第一种, 传给user 一个错误讯息, 说 buffer 已经满了, 不能再写入。 第二种, 将 user 的要求 block 住,等有人将 buffer 内容读走,留出空位时,再让 user 写入资料。 但问题来了, 你要怎么将 user 的要求block 住。难道你要用while ( is_full );write_to_buffer;这样的程序代码吗

6、? 想想看,如果你这样做会发生什么事 ? 第一, kernel 会一直在这个while里执行。第二个,如果kernel 一直在这个while 里执行,表示它没有办法去maintain 系统的运作。那此时系统就相当于当掉了。在这里is_full是一个变量,当然,你可以让is_full是一个function,在这个function里会去做别的事让kernel可以运作,那系统就不会当。这是一个方式。但是,如果我们使用wait_queue 的话,那程序看起来会比较漂亮,而且也比较让人了解,如下所示: struct wait_queue *wq = NULL; /*global variable */w

7、hile ( is_full ) interruptible_sleep_on( &wq );write_to_buffer(); interruptible_sleep_on( &wq ) 是用来将目前的 process,也就是要求写资料到 buffer 的 process 放到wq 这个wait_queue 里。在 interruptible_sleep_on里,则是最后会呼叫schedule() 来做schedule 的动作,也就是去找另一个process 来执行以维持系统的运作。当执行完interruptible_sleep_on之后,要求write 的 process 就会被bloc

8、k 住。那什么时候会恢复执行呢? 这个 process 之所以会被block 住是因为buffer 的空间满了,无法写入。但是如果有人将 buffer 的资料读取掉,则buffer 就有空间可以让人写入。 所以,有关于叫醒process 的动作应该是在 readbuffer 这方面的程序代码做的。extern struct wait_queue*wq;if ( !is_empty ) read_from_buffer();wake_up_interruptible( &wq );. 以上的程序代码应该要放在read buffer 这部分的程序代码里,当 buffer 有多余的空间时 ,我们就呼

9、叫wake_up_interruptible( &wq )来将挂在wq 上的所有process 叫醒。请记得,我是说将wq上的所有process 叫醒,所以,如果如果有 10 个 process挂在 wq上的话,那这 10 个都会被叫醒。之后,至于谁先执行。则是要看schedule 是怎么做的。就是因为这10 个都会被叫醒。如果A 先执行,而且万一很不凑巧的,A 又把buffer 写满了,那其它 9 个 process 要怎么办呢 ? 所以在 write buffer 的部分,需要用一个 while 来检查 buffer 目前是否满了 .如果是的话,那就继续挂在 wq 上面 . 上面所谈的就是

10、wait_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 w

11、ait_queue *wq );interruptible_sleep_on( struct wait_queue *wq );另外两个则是将 process 从 wait_queue 上叫醒的。wake_up( structwait_queue *wq );wake_up_interruptible( struct wait_queue *wq );我现在来解释一下为什么会有两组。有interruptible的那一组是这样子的。当我们去read一个没有资料可供读取的socket时,process会block在那里。如果我们此时按下Ctrl+C,那read()就会传回EINTR。像这种的blo

12、ck 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

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 活动策划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号