linux 管道缓冲区大小,进程间通信:管道(容量与缓冲区)篇 | 术与道的分享

进程间通信(IPC)

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不见。所有进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区读走数据,内核提供的这种机制就是进程间通信(IPC),管道是最基本的IPC机制。

管道容量

管道容量的大小由:pipe buf 和缓冲条目的数目来共同决定其pipe capacity容量。

pipe buf定义的是内核管道缓冲区的容量,这个值由内核设定。我们可以通过ulimit -a命令来查看:

[root@localhost ~]# ulimit -a

pipe size (512 bytes, -p) 8

1

2

[root@localhost~]# ulimit -a

pipesize(512bytes,-p)8

ulimit -a查看到的pipe size一次原子写入为:512 bytes * 8 = 4096 bytes 。

当然另外一个与之对应的就是缓冲条目的个数:它存在于/usr/src/kernels/内核版本/include/linux/pipe_fs_i.h中。当然缓冲条目的个数与linux的内核版本是有关联的,在我的2.6.32-573.el6.x86_64内核上,其缓冲条目个数为:16。

[root@localhost linux]# pwd

/usr/src/kernels/2.6.32-573.el6.x86_64/include/linux

[root@localhost linux]# cat pipe_fs_i.h

#define PIPE_BUFFERS (16)

1

2

3

4

[root@localhostlinux]# pwd

/usr/src/kernels/2.6.32-573.el6.x86_64/include/linux

[root@localhostlinux]# cat pipe_fs_i.h

#define PIPE_BUFFERS (16)

因此就可以得到管道的容量为:16 * 4096 bytes = 65536 bytes。

真正的管道容量即(pipe capacity)。如果你对上述不大理解,我们也可以使用代码来计算管道容量。

当管道满时:

O_NONBLOCK discable: write调用阻塞,直到有程序读走数据。

O_NONBLOCK enable:调用返回-1,errno值为EAGAIN。

管道是一块内存缓冲区,可写下面程序测试管道的容量pipe capacity:

#include

#include

#include

#include

int main()

{

int _pipe[2];

int count = 0;

if(pipe(_pipe) < 0)

{

printf("pipe error\n");

return -1;

}

while(1)

{

write(_pipe[1],"a",sizeof(char));

printf("count = %d\n",++count);

}

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#include

#include

#include

#include

intmain()

{

int_pipe[2];

intcount=0;

if(pipe(_pipe)<0)

{

printf("pipe error\n");

return-1;

}

while(1)

{

write(_pipe[1],"a",sizeof(char));

printf("count = %d\n",++count);

}

return0;

}

count = 1

count = 2

.

.

.

count = 65534

count = 65535

count = 65536

1

2

3

4

5

6

7

8

count=1

count=2

.

.

.

count=65534

count=65535

count=65536

结果也是不言而喻的,当我们一直对管道进行写操作,最后停止的时候即是管道的容量。65536也因此印证了我之前的第一种方法的正确性。

管道缓冲区

在linux中,管道的实现并没有专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。通过将两个file结构指向同一个临时的VFS索引节点,而这个索引节点又指向一个物理页面而实现。如下图所示:

timg.jpg

Drawing6.png

两个file数据结构定义文件操作例程地址是不同的,其中一个是向管道写入数据的例程地址,而另一个是从管道读处数据的例程地址。这样,用户程序的系统调用仍然是通常的文件操作,而内核却利用这种抽象机制实现了管道这一特殊操作。一个普通的管道仅可供具有共同祖先的两个进程之间共享,并且这个祖先已经建立了供他们使用的管道。

注意,在管道中的数据始终以和写数据相同的次序来进行读,这表示lseek()系统调用对管道不起作用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值