1、查看管道容量
通过ulimit -a命令查看自己系统下的管道容量 一次原子写入为512bytes*8=4096bytes
故pipe的容量是512×8×16(缓冲区条目)= 65536
2、程序验证管道容量
算法思想:创建一个管道让其一直写不读取
代码
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int _pipe[2];
if(pipe(_pipe) == -1)
{
perror("pipe");
return 1;
}
int ret;
int count = 0;
int flag = fcntl(_pipe[1],F_GETFL);
fcntl(_pipe[1],F_SETFL,flag|O_NONBLOCK);
while(1)
{
ret = write(_pipe[1],"b",1);
if(ret == -1)
{
printf("error %s\n",strerror(errno));
break;
}
count++;
}
printf("count = %d\n",count);
}
结果截图
3、管道的管理方式
在 Linux 中,管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。通过将两个 file 结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。
有两个 file 数据结构,但它们定义文件操作例程地址是不同的,其中一个是向管道中写入数据的例程地址,而另一个是从管道中读出数据的例程地址。这样,用户程序的系统调用仍然是通常的文件操作,而内核却利用这种抽象机制实现了管道这一特殊操作。
struct inode {
...
struct pipe_inode_info *i_pipe;
...
};
//管道缓冲区个数
#define PIPE_BUFFERS (16)
//管道缓存区对象结构
struct pipe_buffer {
struct page *page; //管道缓冲区页框的描述符地址
unsigned int offset, len; //页框内有效数据的当前位置,和有效数据的长度
struct pipe_buf_operations *ops; //管道缓存区方法表的地址
};
//管道信息结构
struct pipe_inode_info {
wait_queue_head_t wait; //管道等待队列
unsigned int nrbufs, curbuf;
//包含待读数据的缓冲区数和包含待读数据的第一个缓冲区的索引
struct pipe_buffer bufs[PIPE_BUFFERS]; //管道缓冲区描述符数组
struct page *tmp_page; //高速缓存区页框指针
unsigned int start; //当前管道缓存区读的位置
unsigned int readers; //读进程的标志,或编号
unsigned int writers; //写进程的标志,或编号
unsigned int waiting_writers; //在等待队列中睡眠的写进程的个数
unsigned int r_counter; //与readers类似,但当等待写入FIFO的进程是使用
unsigned int w_counter; //与writers类似,但当等待写入FIFO的进程时使用
struct fasync_struct *fasync_readers; //用于通过信号进行的异步I/O通知
struct fasync_struct *fasync_writers; //用于通过信号的异步I/O通知
};