pipefsを追ってみる


Rev.1を表示中。最新版はこちら

  • モジュールインストール時pipe_fs_typeをregister_filesystemでファイルシステムとして登録。
  • kern_mountでvfsmount構造体を作成。そのポインタをスタティック変数pipe_mntにセット。(ただしEXPORTされてないためモジュールから参照できない。)
  • pipefsはdo_add_mountでネームスペースに登録しない。(マウントする必要ないため。)
  • スーパブロック取得コールバックpipefs_get_sbは、get_sb_pseudoをコール。処理はマウントされないスーパブロック情報を設定するヘルパー関数みたいなもの
fs/pipe.c
static struct file_system_type pipe_fs_type = {
       .name           = "pipefs",
       .get_sb         = pipefs_get_sb,
       .kill_sb        = kill_anon_super,
};

static int __init init_pipe_fs(void)
{
       int err = register_filesystem(&pipe_fs_type);

       if (!err) {
               pipe_mnt = kern_mount(&pipe_fs_type);
               if (IS_ERR(pipe_mnt)) {
                       err = PTR_ERR(pipe_mnt);
                       unregister_filesystem(&pipe_fs_type);
               }
       }
       return err;
}
  • pipeもpipe2も do_pipe_flagsを処理の主体。create_write_pipeで書き込み用のパイプ、create_read_pipeで読み込みようパイプ作成。
  • get_unused_fd_flagsで未使用なファイルディスクリプターを2つ取得
  • audit_fd_pairでtask_struct->audit_contextにこの2つのファイルディスクリプターをセット(理由不明)
  • fd_installでfdtable構造体を作成してプロセス->files_struct->fdtableにパイプのfile構造体を結びつける。
  • 呼び出し側に帰り値としてそのァイルディスクリプターをセットする。
int do_pipe_flags(int *fd, int flags)
{
       struct file *fw, *fr;
       int error;
       int fdw, fdr;

       if (flags & ~(O_CLOEXEC | O_NONBLOCK))
               return -EINVAL;

       fw = create_write_pipe(flags);
       if (IS_ERR(fw))
               return PTR_ERR(fw);
       fr = create_read_pipe(fw, flags);
       error = PTR_ERR(fr);
       if (IS_ERR(fr))
               goto err_write_pipe;

       error = get_unused_fd_flags(flags);
       if (error < 0)
               goto err_read_pipe;
       fdr = error;

       error = get_unused_fd_flags(flags);
       if (error < 0)
               goto err_fdr;
       fdw = error;

       error = audit_fd_pair(fdr, fdw);
       if (error < 0)
               goto err_fdw;

       fd_install(fdr, fr);
       fd_install(fdw, fw);
       fd[0] = fdr;
       fd[1] = fdw;

       return 0;
}
  • get_pipe_inodeでパイプ用inodeを作成。(下記参照)
  • d_allocでpipefsのvfsmountのs_rootでdentry作成、pipefs_dentry_operationsでdentryコールバックをセット
  • pipefsのスーパブロック、dentry,およびinodeコールバックを引数にしてalloc_fileでfile構造体を作成。
struct file *create_write_pipe(int flags)
{
       int err;
       struct inode *inode;
       struct file *f;
       struct dentry *dentry;
       struct qstr name = { .name = "" };

       err = -ENFILE;
       inode = get_pipe_inode();
       if (!inode)
               goto err;

       err = -ENOMEM;
       dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
       if (!dentry)
               goto err_inode;

       dentry->d_op = &pipefs_dentry_operations;
       dentry->d_flags &= ~DCACHE_UNHASHED;
       d_instantiate(dentry, inode);

       err = -ENFILE;
       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
       if (!f)
               goto err_dentry;
       f->f_mapping = inode->i_mapping;

       f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
       f->f_version = 0;

       return f;
}
  • inodeで設定できない属性をpipe_inode_infoで設定するためpipe_inode_infoでinodeを包んでいます。
static struct inode * get_pipe_inode(void)
{
       struct inode *inode = new_inode(pipe_mnt->mnt_sb);
       struct pipe_inode_info *pipe;

       if (!inode)
               goto fail_inode;

       pipe = alloc_pipe_info(inode);

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) {
               init_waitqueue_head(&pipe->wait);
               pipe->r_counter = pipe->w_counter = 1;
               pipe->inode = inode;


最終更新 2010/01/19 19:44:54 - north
(2010/01/19 19:44:54 作成)


検索

アクセス数
3702960
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。