• 管道在linux的实现


    //定义一个文件系统的类型
    static DECLARE_FSTYPE(pipe_fs_type,"pipefs",pipefs_read_super,FS_NOMOUNT);

    //管道超级块
    static struct super_block *pipefs_read_super(struct super_block *sb,void *data,int silent)
    {
    struct inode *root=new inode(sb); //生成管道文件系统的根目录的内存inode

    if(!root)
    return NULL;
    root->imode=S_IFDIR|S_IRUSR|S_IWUSR;
    root->i_uid=root->i_gid=0;
    root->i_atime=root->mtime=root->i_ctime=CURRENT_TIME;
    sb->s_blocksize=1024;
    sb->s_blocksize_bits=10;
    sb->s_magic=PIPEFS_MAGIC;
    sb->s_op=&pipefs_ops; //设置超级块sb的s_ob域的值为pipefs_ops结构的指针。
    sb->s_root=d_alloc(NULL,&(const struct qstr) {"pipe:",5,0}); //设置超级块的s_root域,s_root域的类型是struct dentry*,指向根目录的对象
    if(!sb->s_root)
    {
    iput(root);
    return NULL;
    }
    sb->s_root->d_sb=sb;
    sb->s_root->d_parent=sb->s_root; //将刚分配的目录项对象与前面生成的根目录inode连接起来
    d_instantiate(sb->s_root,root);
    return sb;
    }

    static struct super_operations pipefs_ops=
    {
    statfs:pipefs_statfs,
    };

    struct pipe_inode_info
    {
    wait_queue_head_t wait; //管道等待队列指针wait
    char *base; //内核缓冲区基地址base
    unsigned int len;
    unsigned int start;
    unsigned int readers;
    unsigned int writers;
    unsigned int waiting_readers;
    unsigned int waiting_writers;
    unsigned int r_counter;
    unsigned int w_counter;
    };


    #define PIPE_SIZE PAGE_SIZE

    #define PIPE_SEM(inode) (&(inode).i_sem)
    #define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
    #define PIPE_BASE(inode) (&(inode).i_pipe->base)
    #define PIPE_START(inode) (&(inode).i_pipe->start)
    #define PIPE_LEN(inode) (&(inode).i_pipe->len)
    #define PIPE_READERS(inode) (&(inode).i_pipe->readers)
    #define PIPE_WRITERS(inode) (&(inode).i_pipe->writers)
    #define PIPE_WAITINT_READERS(inode) (&(inode).i_pipe->waiting_readers)
    #define PIPE_WAITINT_WRITERS(inode) (&(inode).i_pipe->waitint_writers)
    #define PIPE_RCOUNTER(inode) (&(inode).i_pipe->r_counter)
    #define PIPE_WCOUNTER(inode) (&(inode).i_pipe->w_counter)

    #define PIPE_EMPTY(inode) (PIPE_LEN(inode)==0)
    #define PIPE_FULL(inode) (PIPE_LEN(inode)==PIPE_SIZE)
    #define PIPE_FREE(inode) (PIPE_SIZE-PIPE_LEN(inode))
    #define PIPE_END(inode) ((PIPE_START(inode)+PIPE_LEN(inode))&(PIPE_SIZE-1))
    #define PIPE_MAX_RCHUNK(inode) (PIPE_SIZE-PIPE_START(inode))
    #define PIPE_MAX_WCHUNK(inode) (PIPE_SIZE-PIPE_PIPE_END(inode))

    #define PIPE_BUF 4096

    struct file_operations read_pipe_fops={
    llseek:pipe_lseek,
    read:pipe_read,
    write:bad_pipe_w,
    poll:pipe_poll,
    ioctl:pipe_ioctl,
    open:pipe_open,
    release:pipe_read_release,
    };


    //管道的建立与释放
    int do_pipe(int *fd)
    {
    struct qstr this;
    char name[32];
    struct dentry *dentry;
    struct inode *inode;
    struct file *f1,*f2;
    int error;
    int i,j;

    error=-ENFILE;
    f1=get_empty_filp();
    if(!f1)
    goto no_files;

    f2=get_empty_filp();
    if(!f2)
    goto close_f1;

    inode=get_pipe_node();
    if(!inode)
    goto close_f12;

    error=get_unused_fd();
    if(error<0)
    goto close_f12_inode;
    i=error;

    error=get_unused_fd();
    if(error<0)
    goto close_f12_inode_i;
    j=error;

    error=-ENOMEM;
    sprintf(name,"[%lu]",inode->i_ino);
    this.name=name;
    this.len=strlen(name);
    this.hash=inode->i_ino;
    dentry=d_alloc(pipe_mnt->mnt_sb->s_root,&this); //生成一个目录项对象dentry,并通过它将上述两个文件对象与管道索引节点联系起来
    if(!dentry)
    {
    goto close_f12_inode_i_j;
    }
    dentry->d_op=&pipefs_dentry_operations;
    d_add(dentry,inode);
    f1->f_vfsmnt=f2->f_vfsmnt=mntget(mntget(pipe_mnt));
    f2->f_dentry=f1->f_dentry=dget(dentry);

    f1->f_pos=f2->pos=0;
    f1->f_flags=O_RDONLY;
    f1->f_op=&read_pipe_fops;
    f1->f_mode=1;
    f1->f_version=0;

    f2->f_flags=O_WRONLY;
    f2->f_op=&write_pipe_fops;
    f2->f_mode=2;
    f2->f_version=0;

    fd_install(i,f1); //将两个文件对象与上述两个文件描述符联系起来
    fd_install(j,f2);
    fd[0]=i;
    fd[1]=j;
    return 0;

    close_f12_inode_i_j:
    put_unused_fd(j);
    close_f12_inode_i:
    put_unused_fd(i);
    close_f12_inode:
    free_page((unsigned long)PIPE_BASE(*inode));
    kfree(inode->i_pipe);
    inode->i_pipe=NULL;
    iput(inode);
    close_f12:
    put_filp(f2);
    close_f1:
    put_filp(f1);
    no_files:
    return error;
    }
    Live together,or Die alone!
  • 相关阅读:
    js实现发布订阅模式
    js对象拷贝方法
    编译原理中的词法和语法分析怎么理解?
    js数组去重
    js对象判断方法
    js实现深度比较
    js遍历方法总结
    AngularJS入门教程08:更多模板
    任务,责任,过错之间的平衡问题
    C#操作Excel总结
  • 原文地址:https://www.cnblogs.com/hzhida/p/2395660.html
Copyright © 2020-2023  润新知