Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48034
  • 博文数量: 30
  • 博客积分: 2000
  • 博客等级: 大尉
  • 技术积分: 230
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-07 21:27
文章分类
文章存档

2011年(1)

2009年(29)

我的朋友

分类: LINUX

2009-08-08 19:18:33

所谓管道么,想想家里的水管吧——自来水厂那头给我们送水,我们这头打开水龙头自来水就哗哗的流出来了,水怎么从自来水厂输送过来的?答案就是管道,当然我们这里通常称它为水管。

所以由上面定义,什么叫管道?就是从一个进程里要传东西给另一个进程,类似我们的输送自来水了,我们就借助一"根"管道,把要传的东西传了过去。

来举个小例子吧:

比如

$ ls -l | grep mbox

上 面的命令,将 ls -l的输入作为grep的输入,这种方式称为管道。这个命令原意是列出当前的信息(ls -l),然后用grep 命令在列出的当前信息中检索出含有mbox的信息。也就是说ls -l 我们通过这个命令得到的信息,然后传入到grep mbox命令中,作为输入信息。Linux提供了很多功能强大的小命令,但使用管道将这些命令组合起来,就形成了非常强大的工具组合,能完成非常复杂的工 作。

上节说了我对Linux管道的一点儿小见解,这节来看看内核中关于管道的实现代码。

  以下代码摘自 Linux/include/fs.h

#define PIPE_HEAD(inode) ((inode).i_zone[0])  //这里定义了管道头

 

#define PIPE_TAIL(inode) ((inode).i_zone[1])  //呃,这里定义的管道尾
 

管道的头尾我们都定义了,大家回头来看看管道的size 的定义:

 

#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1)) 

这里用 (管道头-管道尾)%pagesize 取余数 从而取得了管道大小,关于这个取余数的问题,我在《求余不用模》 中已经详细阐释了这种方法的数学原理。但是这段代码最值得探讨的倒还不是这块内容。我们来看看管道的抽象图:

假设管道大小是4,(请注意管道大小必须要选择2n种形式),我们看看上图如果管头指针指向3,而管尾指针指向的是1,那么管道的大小按照上面的算法,我们得出管道大小为2 (即是(3-1)&3),那么我们有理由说上图管道头的指针指向的3号元素其实是空的!而我们不妨再假设如果是管头指向的是1,而管尾指向的是3,那么按照上面的做法(1-3)&3,最后得出的是2,注意这里虽然是负数但是用这种办法仍然奏效。

说了这么多,其实可能有人早就注意到了管道是个队列的数组结构,而且还是队列的一种特殊形式——循环队列。

对于这种队列,我们通常空出了一个元素位置来表达队列是否已满。比如如果rear==front 则表示管道为空,如果为满的话就不能还用这个表示了,(不然我们如何区分究竟谁是满的谁是空的), 通常是在队头空出一个位置,比如这里我们就是用rear==front+1 表示已满!

回到内核代码中,看看Linus怎么定义的:

 

#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
跟我们推理的一样,为空则头和尾相等,为满则rear=
front+1,也就是(PIPE_SIZE(inode)==(PAGE_SIZE-1)
阅读(647) | 评论(0) | 转发(0) |
0

上一篇:Linux内核之电梯算法

下一篇:求余不用模

给主人留下些什么吧!~~