pipeバッファ
実装イメージ
#define PIPE_DEF_BUFFERS 16 truct pipe_inode_info { wait_queue_head_t wait; unsigned int nrbufs, curbuf, buffers; unsigned int readers; unsigned int writers; 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 inode *inode; struct pipe_buffer *bufs; }; 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 * alloc_pipe_info(struct inode *inode) { struct pipe_inode_info *pipe; pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); if (pipe) { pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL); if (pipe->bufs) { init_waitqueue_head(&pipe->wait); pipe->r_counter = pipe->w_counter = 1; pipe->inode = inode; pipe->buffers = PIPE_DEF_BUFFERS; return pipe; } kfree(pipe); } return NULL; }デフォルのパイプサイズはsizeof(struct pipe_buffer)のstruct pipe_bufferのpage*PIPE_DEF_BUFFERS
inode = new_inode_pseudo(pipe_mnt->mnt_sb); struct pipe_inode_info pipe = alloc_pipe_info(inode) { inode->i_pipe = pipe; } pfile.dentry->d_inode = inode; pfile.dentry->d_inode->i_pipe.buffers = PIPE_DEF_BUFFERS pfile.dentry->d_inode->i_pipe.bufs = sizeof(struct pipe_buffer)*PIPE_DEF_BUFFERS; struct pipe_buffer *writing-pipe = pfile.dentry->d_inode->i_pipe.bufs + writing-position strcpy(writing-pipe->page, data, strlen(data));
サンプル
[root@v.north]# cat pipe-write.c#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #define PAGE_SIZE 4096 #define PIPE_DEF_BUFFERS 16 int main(int argc, char *argv[]) { int pipefd[2]; char *wbuf, rbuf[10]; int cnt, wcnt, tcnt, pipe_size, write_size; wcnt = atoi(argv[1]); wbuf = "11111111111111111111111111111111111111111111111111"; tcnt = 0; pipe2(pipefd, O_NONBLOCK); while(1) { cnt = write(pipefd[1], wbuf, wcnt); if(cnt <= 0) { break; } tcnt += cnt; } pipe_size = PAGE_SIZE*PIPE_DEF_BUFFERS; write_size = tcnt; printf("pipe buff:%d writed size:%d\n", pipe_size, write_size); printf("empty size by pipe buff :%d\n", pipe_size - write_size); printf("empty size by each page:%d\n", (PAGE_SIZE % wcnt)*PIPE_DEF_BUFFERS); printf("\n"); }[root@v.north]# ./pipe-write.out 1 <=2^0
pipe buff:65536 writed size:65536
empty size by pipe buff :0
empty size by each page:0
[root@v.north]# ./pipe-write.out 2 <=2^1
pipe buff:65536 writed size:65536
empty size by pipe buff :0
empty size by each page:0
[root@v.north]# ./pipe-write.out 3
pipe buff:65536 writed size:65520
empty size by pipe buff :16
empty size by each page:16
[root@v.north]# ./pipe-write.out 4 <=2^2
pipe buff:65536 writed size:65536
empty size by pipe buff :0
empty size by each page:0
[root@v.north]# ./pipe-write.out 5
pipe buff:65536 writed size:65520
empty size by pipe buff :16
empty size by each page:16
[root@v.north]# ./pipe-write.out 6
pipe buff:65536 writed size:65472
empty size by pipe buff :64
empty size by each page:64
[root@v.north]# ./pipe-write.out 7
pipe buff:65536 writed size:65520
empty size by pipe buff :16
empty size by each page:16
[root@v.north]# ./pipe-write.out 8 <=2^3
pipe buff:65536 writed size:65536
empty size by pipe buff :0
empty size by each page:0
empty size by pipe buff>書き込みサイズで書き込みできないのは、empty size by pipe buffは、page単位の空サイズの合計
追記
書き込みをサイズ毎に行う場合、パイプの全バッファ有効利用のため、書き込みサイズは2のべき乗とすべき。通常ファイルオペレーションの書き込みは、generic_file_aio_writeによるファイルキャッシュへの書き込みとなるが、pipeは異るファイル間でのデータ共有とすべく、ファイルキャッシュでないpipe_writeによる上記実装となっている。
const struct file_operations write_pipefifo_fops = { .llseek = no_llseek, .read = bad_pipe_r, .write = do_sync_write, .aio_write = pipe_write, .poll = pipe_poll, .unlocked_ioctl = pipe_ioctl, .open = pipe_write_open, .release = pipe_write_release, .fasync = pipe_write_fasync, };