一、pipe的容量node
2.6標準版本的linux內核,pipe緩衝區是64KB,儘管命令ulimit -a看到管道大小8塊,緩衝區的大小不是4 k,由於內核動態分配最大16「緩衝條目」,乘64 k。這些限制是硬編碼的linux
二、如何查看本身pc上的pipe多大數組
1)經過ulimit -a查看到 pipe size 一次原子寫入爲:512Bytes*8=4096Bytes 緩存
查看緩衝條目個數:cat /usr/src/kernels/3.10.0-327.el7.x86_64/include/linux/pipe_fs_i.h文件數據結構
因此個人pc下得pipe緩衝大小爲:16*4096=65536Bytesapp
也就驗證了man 7 pipe下的pipe capacity異步
三、pipe的內部組織方式async
在 Linux 中,管道的實現並無使用專門的數據結構,而是藉助了文件系統的file結構和VFS的索引節點inode。經過將兩個 file 結構指向同一個臨時的 VFS 索引節點,而這個 VFS 索引節點又指向一個物理頁面而實現的。ide
有兩個 file 數據結構,但它們定義文件操做例程地址是不一樣的,其中一個是向管道中寫入數據的例程地址,而另外一個是從管道中讀出數據的例程地址。這樣,用戶程序的系統調用仍然是一般的文件操做,而內核卻利用這種抽象機制實現了管道這一特殊操做。this
cat /usr/src/kernels/3.10.0-327.el7.x86_64/include/linux/pipe_fs_i.h文件
#ifndef _LINUX_PIPE_FS_I_H #define _LINUX_PIPE_FS_I_H #define PIPE_DEF_BUFFERS 16 #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ #define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ /** * struct pipe_buffer - a linux kernel pipe buffer * @page: the page containing the data for the pipe buffer * @offset: offset of data inside the @page * @len: length of data inside the @page * @ops: operations associated with this buffer. See @pipe_buf_operations. * @flags: pipe buffer flags. See above. * @private: private data owned by the ops. **/ struct pipe_buffer { struct page *page; unsigned int offset, len; const struct pipe_buf_operations *ops; unsigned int flags; unsigned long private; }; /** * struct pipe_inode_info - a linux kernel pipe * @mutex: mutex protecting the whole thing * @wait: reader/writer wait point in case of empty/full pipe * @nrbufs: the number of non-empty pipe buffers in this pipe * @buffers: total number of buffers (should be a power of 2) * @curbuf: the current pipe buffer entry * @tmp_page: cached released page * @readers: number of current readers of this pipe * @writers: number of current writers of this pipe * @files: number of struct file refering this pipe (protected by ->i_lock) * @waiting_writers: number of writers blocked waiting for room * @r_counter: reader counter * @w_counter: writer counter * @fasync_readers: reader side fasync * @fasync_writers: writer side fasync * @bufs: the circular array of pipe buffers **/ struct pipe_inode_info { struct mutex mutex; wait_queue_head_t wait; unsigned int nrbufs, curbuf, buffers; unsigned int readers; unsigned int writers; unsigned int files; unsigned int waiting_writers; unsigned int r_counter; unsigned int w_counter; struct page *tmp_page; struct fasync_struct *fasync_readers; struct fasync_struct *fasync_writers; struct pipe_buffer *bufs; }; /* * Note on the nesting of these functions: * * ->confirm() * ->steal() * ... * ->map() * ... * ->unmap() * * That is, ->map() must be called on a confirmed buffer, * same goes for ->steal(). See below for the meaning of each * operation. Also see kerneldoc in fs/pipe.c for the pipe * and generic variants of these hooks. */ struct pipe_buf_operations { /* * This is set to 1, if the generic pipe read/write may coalesce * data into an existing buffer. If this is set to 0, a new pipe * page segment is always used for new data. */ int can_merge; /* * ->map() returns a virtual address mapping of the pipe buffer. * The last integer flag reflects whether this should be an atomic * mapping or not. The atomic map is faster, however you can't take * page faults before calling ->unmap() again. So if you need to eg * access user data through copy_to/from_user(), then you must get * a non-atomic map. ->map() uses the kmap_atomic slot for * atomic maps, you have to be careful if mapping another page as * source or destination for a copy. */ void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int); /* * Undoes ->map(), finishes the virtual mapping of the pipe buffer. */ void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *); /* * ->confirm() verifies that the data in the pipe buffer is there * and that the contents are good. If the pages in the pipe belong * to a file system, we may need to wait for IO completion in this * hook. Returns 0 for good, or a negative error value in case of * error. */ int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *); /* * When the contents of this pipe buffer has been completely * consumed by a reader, ->release() is called. */ void (*release)(struct pipe_inode_info *, struct pipe_buffer *); /* * Attempt to take ownership of the pipe buffer and its contents. * ->steal() returns 0 for success, in which case the contents * of the pipe (the buf->page) is locked and now completely owned * by the caller. The page may then be transferred to a different * mapping, the most often used case is insertion into different * file address space cache. */ int (*steal)(struct pipe_inode_info *, struct pipe_buffer *); /* * Get a reference to the pipe buffer. */ void (*get)(struct pipe_inode_info *, struct pipe_buffer *); }; /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ #define PIPE_SIZE PAGE_SIZE /* Pipe lock and unlock operations */ void pipe_lock(struct pipe_inode_info *); void pipe_unlock(struct pipe_inode_info *); void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); extern unsigned int pipe_max_size, pipe_min_size; int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *); /* Drop the inode semaphore and wait for a pipe event, atomically */ void pipe_wait(struct pipe_inode_info *pipe); struct pipe_inode_info *alloc_pipe_info(void); void free_pipe_info(struct pipe_inode_info *); /* Generic pipe buffer ops functions */ void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int); void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *); void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); /* for F_SETPIPE_SZ and F_GETPIPE_SZ */ long pipe_fcntl(struct file *, unsigned int, unsigned long arg); struct pipe_inode_info *get_pipe_info(struct file *file); int create_pipe_files(struct file **, int); #endif
將上面的文件進行提取重要的結構
//inode結點信息結構 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通知 };