無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

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,
};

最終更新 2017/11/16 14:37:43 - north
(2014/04/03 23:49:21 作成)