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

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

mkfifo


pipeはread/writeのみファイルですが、fifoはread/write/read_writeで、pipeで実装されてない1ファイルのread/writeが可能で、又多重openする事はdup2に相当します。

サンプル
[root@localhost c]# cat fifo.c
#include<stdio.h>
#include<fcntl.h>
#include<string.h>

void    read_fifo(int   fd)
{
       char    buf[12];

       memset(buf, 0, sizeof(buf));
       read(fd, buf, 4);
       printf("%s\n", buf);
}

void main()
{
       int     fd1, fd2, fd3;

       fd1=open("fifo",O_RDWR);
       fd2=open("fifo",O_RDWR);
       fd3=open("fifo",O_RDWR);

       write(fd1,"12345", 5);
       write(fd2,"67890", 5);
       write(fd3,"abcde", 5);

       read_fifo(fd3);
       read_fifo(fd2);
       read_fifo(fd1);
}

[root@localhost c]# mkfifo fifo
[root@localhost c]# ls -l fifo
prw-r--r-- 1 root root 0 10月 21 01:50 fifo
[root@localhost c]# ./fifo.o
1234
5678
90ab
mkfifoのスペシャルファイルのdentryのinodeにinode->i_fop = &def_fifo_fopsとし、openがdef_fifo_fops.openコールされ、fileのread/writeコールバックをpipeのread/writeとする事で、ファイルによる読書でpipe読書きの実装となります。

mknodシステムコールからファイルシステム依存のmknodコールバック(ext3_mknod)で、inode->i_mode = S_IFIFO/inode->i_fop = &def_fifo_fopsとするinodeを作成します。このスペシャルファイルのinodeオープンでdef_fifo_fops.open=fifo_openがコールされ、下記の掛かるコールバックが設定されます。

READ : filp->f_op = &read_pipefifo_fops
WRITE : filp->f_op = &write_pipefifo_fops;
READ_WITE: filp->f_op = &rdwr_pipefifo_fops;
#define S_IFIFO  0010000

static int ext3_mknod (struct inode * dir, struct dentry *dentry,
                       umode_t mode, dev_t rdev)
{
       handle_t *handle;
       struct inode *inode;
       int err, retries = 0;

       if (!new_valid_dev(rdev))
               return -EINVAL;

       dquot_initialize(dir);

retry:
       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
                                       EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
       if (IS_ERR(handle))
               return PTR_ERR(handle);

       if (IS_DIRSYNC(dir))
               handle->h_sync = 1;

       inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
       err = PTR_ERR(inode);
       if (!IS_ERR(inode)) {
               init_special_inode(inode, inode->i_mode, rdev);
               err = ext3_add_nondir(handle, dentry, inode);
       }
       ext3_journal_stop(handle);
       if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
               goto retry;
       return err;
}

const struct file_operations def_fifo_fops = {
       .open           = fifo_open, 
       .llseek         = noop_llseek,
};

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
       inode->i_mode = mode;
       if (S_ISCHR(mode)) {
               inode->i_fop = &def_chr_fops;
               inode->i_rdev = rdev;
       } else if (S_ISBLK(mode)) {
               inode->i_fop = &def_blk_fops;
               inode->i_rdev = rdev;
       } else if (S_ISFIFO(mode))
               inode->i_fop = &def_fifo_fops;
       else if (S_ISSOCK(mode))
               inode->i_fop = &bad_sock_fops;
       else
               printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
                                 " inode %s:%lu\n", mode, inode->i_sb->s_id,
                                 inode->i_ino);
}
pipeのinodeは、ブロックデバイスをメモリとするmount_pseudoでマウントされたpipefsファイルシステムのpipe管理情報を有するinodeで、引数のinodeはスペシャルファイルのinode故、alloc_pipe_info()でpipe情報のinode->i_pipe = pipeとされます。
static int fifo_open(struct inode *inode, struct file *filp)
{
       struct pipe_inode_info *pipe;
       int ret;

       mutex_lock(&inode->i_mutex);
       pipe = inode->i_pipe;
       if (!pipe) {
               ret = -ENOMEM;
               pipe = alloc_pipe_info(inode);
               if (!pipe)
                       goto err_nocleanup;
               inode->i_pipe = pipe;
       }
       filp->f_version = 0;

       filp->f_mode &= (FMODE_READ | FMODE_WRITE);

       switch (filp->f_mode) {
       case FMODE_READ:
               filp->f_op = &read_pipefifo_fops;
               pipe->r_counter++;
               if (pipe->readers++ == 0)
                       wake_up_partner(inode);

               if (!pipe->writers) {
                       if ((filp->f_flags & O_NONBLOCK)) {
                               filp->f_version = pipe->w_counter;
                       } else {
                               wait_for_partner(inode, &pipe->w_counter);
                               if(signal_pending(current))
                                       goto err_rd;
                       }
               }
               break;
       
       case FMODE_WRITE:
               ret = -ENXIO;
               if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
                       goto err;

               filp->f_op = &write_pipefifo_fops;
               pipe->w_counter++;
               if (!pipe->writers++)
                       wake_up_partner(inode);

               if (!pipe->readers) {
                       wait_for_partner(inode, &pipe->r_counter);
                       if (signal_pending(current))
                               goto err_wr;
               }
               break;
       
       case FMODE_READ | FMODE_WRITE:
               filp->f_op = &rdwr_pipefifo_fops;

               pipe->readers++;
               pipe->writers++;
               pipe->r_counter++;
               pipe->w_counter++;
               if (pipe->readers == 1 || pipe->writers == 1)
                       wake_up_partner(inode);
               break;

       default:
               ret = -EINVAL;
               goto err;
       }

       mutex_unlock(&inode->i_mutex);
       return 0;

err_rd:
       if (!--pipe->readers)
               wake_up_interruptible(&pipe->wait);
       ret = -ERESTARTSYS;
       goto err;

err_wr:
       if (!--pipe->writers)
               wake_up_interruptible(&pipe->wait);
       ret = -ERESTARTSYS;
       goto err;

err:
       if (!pipe->readers && !pipe->writers)
               free_pipe_info(inode);

err_nocleanup:
       mutex_unlock(&inode->i_mutex);
       return ret;
}


最終更新 2016/10/21 16:30:45 - north
(2015/11/10 14:20:45 作成)