管道在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;
}
posted @ 2012-03-14 12:01  苍术厚朴  阅读(498)  评论(0编辑  收藏  举报