pipeバッファ
Rev.6を表示中。最新版はこちら。
実装イメージ
#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^0pipe 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
追記
書き込みをサイズ毎に行う場合、パイプの全バッファ有効利用のため、書き込みサイズは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,
};






