jhluroom 弹jhluroom.blog.chinaunix.net
jhluroom
全部博文(137)
mm(2)
fs(17)
math(1)
boot(3)
init(0)
kernel(12)
blk_drv(4)
chr_drv(5)
源码疑问(1)
2011年(10)
2010年(23)
2009年(104)
高傲的活
小雅贝贝
along819
shiyigud
mcc543
yunpeng_
cynthia
pppstar
Bsolar
badb0y
dadada林
分类: LINUX
2009-08-19 10:45:36
/* * linux/fs/pipe.c * * (C) 1991 Linus Torvalds */#include <signal.h>#include <linux/sched.h>#include <linux/mm.h> /* for get_free_page */#include <asm/segment.h>//一个管道占4 块,管道缓冲区长度PAGE_SIZE,,管道数据和长度PIPE_SIZE,inode->i_size:管道缓冲区指针?node->i_zone[0]:管道数据 头指针,node->i_zone[0]:管道数据 尾指针int read_pipe(struct m_inode * inode, char * buf, int count)// 管道读操作函数。{// 参数inode 是管道对应的i 节点,buf 是数据缓冲区指针,count 是读取的字节数据 int chars, size, read = 0; while (count>0) { while (!(size=PIPE_SIZE(*inode))) {//如果当前管道中没有数据 wake_up(&inode->i_wait);//则唤醒等待该节点的进程,这里通常是写管道进程 if (inode->i_count != 2) //引用节点小于2,则说明没有写管道,返回已读数据/* are there any writers? */ return read; sleep_on(&inode->i_wait);//将本进程 睡眠,链入inode->i_wait队列中来 } chars = PAGE_SIZE-PIPE_TAIL(*inode);//取管道尾到缓冲区末端的字节数chars if (chars > count)//如果其大于还需要读取的字节数count,则令其等于count chars = count; if (chars > size)//如果chars 大于当前管道中含有数据的长度size,则令其等于size chars = size; count -= chars;//还有多少没有读 read += chars;//已读的个数 size = PIPE_TAIL(*inode);// 令size 指向管道数据尾部 PIPE_TAIL(*inode) += chars;//调整管道数据尾指针位置 PIPE_TAIL(*inode) &= (PAGE_SIZE-1);//尾指针超过管道末端则返回 while (chars-->0)// 将管道中的数据复制到用户缓冲区中 put_fs_byte(((char *)inode->i_size)[size++],buf++); } wake_up(&inode->i_wait);// 唤醒等待该管道i 节点的进程,并返回读取的字节数 return read;} int write_pipe(struct m_inode * inode, char * buf, int count)// 管道写操作函数{// 参数inode 是管道对应的i 节点,buf 是数据缓冲区指针,count 是将写入管道的字节数 int chars, size, written = 0; while (count>0) { while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {// 若当前管道中没有已经满了, wake_up(&inode->i_wait);//则唤醒等待该节点的进程 if (inode->i_count != 2) { //如果已没有读管道者, /* no readers */ current->signal |= (1<<(SIGPIPE-1));//则向进程发送SIGPIPE 信号 return written?written:-1;//并返回已写入的字节数并退出 } sleep_on(&inode->i_wait);//如果此节点引用数大于或等于2,则说明可能有读管道存在,则将此写进程睡眠于inode->i_wait队列 } chars = PAGE_SIZE-PIPE_HEAD(*inode);//取管道尾到缓冲区末端的字节数chars if (chars > count)//同前 chars = count; if (chars > size)//同前 chars = size; count -= chars;//同前 written += chars;//同前 size = PIPE_HEAD(*inode);//同前 PIPE_HEAD(*inode) += chars;//同前 PIPE_HEAD(*inode) &= (PAGE_SIZE-1);//同前 while (chars-->0)//同前 ((char *)inode->i_size)[size++]=get_fs_byte(buf++); } wake_up(&inode->i_wait);//同前 return written;}int sys_pipe(unsigned long * fildes)// 创建管道系统调用函数{/// 在fildes 所指的数组中创建一对文件句柄(描述符)。这对文件句柄指向一管道i 节点。fildes[0] 用于读管道中数据,fildes[1]用于向管道中写入数据 struct m_inode * inode; struct file * f[2]; int fd[2]; int i,j; j=0; for(i=0;j<2 && i<NR_FILE;i++)// 从系统文件表中取两个空闲项(引用计数字段为0 的项),并分别设置引用计数为1 if (!file_table[i].f_count) (f[j++]=i+file_table)->f_count++; if (j==1)// 如果只有一个空闲项,则释放该项(引用计数复位) f[0]->f_count=0; if (j<2)// 如果没有找到两个空闲项,则返回-1 return -1; j=0;// 针对上面取得的两个文件结构项,分别分配一文件句柄,并使进程的文件结构指针分别指向这两个文件结构 for(i=0;j<2 && i<NR_OPEN;i++) if (!current->filp[i]) { current->filp[ fd[j]=i ] = f[j]; j++; } if (j==1)// 如果只有一个空闲文件句柄,则释放该句柄 current->filp[fd[0]]=NULL; if (j<2) {// 如果没有找到两个空闲句柄,则释放上面获取的两个文件结构项(复位引用计数值),并返回-1 f[0]->f_count=f[1]->f_count=0; return -1; } if (!(inode=get_pipe_inode())) {// 获取管道节点。返回为i 节点指针(如果是NULL 则失败) current->filp[fd[0]] = current->filp[fd[1]] = NULL; f[0]->f_count = f[1]->f_count = 0; return -1; } f[0]->f_inode = f[1]->f_inode = inode;// 指向对应i 节点 f[0]->f_pos = f[1]->f_pos = 0;// 文件位置(读写偏移值) f[0]->f_mode = 1; //第一个置读 /* read */ f[1]->f_mode = 2; //第二个置写 /* write */ put_fs_long(fd[0],0+fildes);// 将文件句柄数组复制到对应的用户管道数组中 put_fs_long(fd[1],1+fildes);// 将文件句柄数组复制到对应的用户管道数组中 return 0;}
上一篇:file_dev.c
下一篇:char_dev.c
登录 注册