Chinaunix首页 | 论坛 | 博客
  • 博客访问: 585567
  • 博文数量: 137
  • 博客积分: 4040
  • 博客等级: 上校
  • 技术积分: 1584
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-08 13:05
文章分类

全部博文(137)

文章存档

2011年(10)

2010年(23)

2009年(104)

分类: 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;
}

阅读(757) | 评论(0) | 转发(0) |
0

上一篇:file_dev.c

下一篇:char_dev.c

给主人留下些什么吧!~~