管中窥道——我看Linux内核管道

本文深入解析Linux内核中管道的实现机制,重点介绍了管道头、尾的定义方式及管道大小的计算方法,并通过实例展示了循环队列的应用。
 

管中窥道——记录Linux内核管道(2)

刺猬@http://blog.youkuaiyun.com/littlehedgehog

 





上节说了我对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)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值