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

全部博文(137)

文章存档

2011年(10)

2010年(23)

2009年(104)

分类: LINUX

2009-08-19 11:47:44

/*
 * linux/fs/read_write.c
 *
 * (C) 1991 Linus Torvalds
 */


#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>

#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/segment.h>

extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);// 字符设备读写函数。

extern int read_pipe(struct m_inode * inode, char * buf, int count);// 读管道操作函数。

extern int write_pipe(struct m_inode * inode, char * buf, int count);// 写管道操作函数

extern int block_read(int dev, off_t * pos, char * buf, int count);// 块设备读操作函数

extern int block_write(int dev, off_t * pos, char * buf, int count);// 块设备写操作函数

extern int file_read(struct m_inode * inode, struct file * filp,
        char * buf, int count);// 读文件操作函数

extern int file_write(struct m_inode * inode, struct file * filp,
        char * buf, int count);// 写文件操作函数


int sys_lseek(unsigned int fd,off_t offset, int origin)// 重定位文件读写指针系统调用函数

{// 参数fd 是文件句柄,offset 是新的文件读写指针偏移值,origin 是偏移的起始位置,是SEEK_SET(0,从文件开始处)、SEEK_CUR(1,从当前读写位置)、SEEK_END(2,从文件尾处)三者之一。

    struct file * file;
    int tmp;
// 如果文件句柄值大于程序最多打开文件数NR_OPEN(20),或者该句柄的文件结构指针为空,或者 对应文件结构的i 节点字段为空,或者指定设备文件指针是不可定位的,则返回出错码并退出

    if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
     || !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
        return -EBADF;
    if (file->f_inode->i_pipe)// 如果文件对应的i 节点是管道节点,则返回出错码,退出。管道头尾指针不可随意移动

        return -ESPIPE;
    switch (origin) {// 根据设置的定位标志,分别重新定位文件读写指针

        case 0://origin = SEEK_SET,要求以文件起始处作为原点设置文件读写指针

            if (offset<0) return -EINVAL;
            file->f_pos=offset;
            break;
        case 1://origin = SEEK_CUR,要求以文件当前读写指针处作为原点重定位读写指针

            if (file->f_pos+offset<0) return -EINVAL;
            file->f_pos += offset;
            break;
        case 2://origin = SEEK_END,要求以文件末尾作为原点重定位读写指针

            if ((tmp=file->f_inode->i_size+offset) < 0)
                return -EINVAL;
            file->f_pos = tmp;
            break;
        default:
            return -EINVAL;
    }
    return file->f_pos;//返回重新定位后的文件指针位置

}

int sys_read(unsigned int fd,char * buf,int count)// 读文件系统调用函数

{// 参数fd 是文件句柄,buf 是缓冲区,count 是欲读字节数

    struct file * file;
    struct m_inode * inode;
// 如果文件句柄值大于程序最多打开文件数NR_OPEN,或者需要读取的字节计数值小于0,或者该句柄的文件结构指针为空,则返回出错码并退出

if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
        return -EINVAL;
    if (!count)// 若需读取的字节数count 等于0,则返回0

        return 0;
    verify_area(buf,count);// 验证存放数据的缓冲区内存限制

    inode = file->f_inode;// 取文件对应的i 节点

    if (inode->i_pipe)//若是管道文件

        return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
    if (S_ISCHR(inode->i_mode))//为字符设备,inode->i_zone[0]存放着设备号

        return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
    if (S_ISBLK(inode->i_mode))//为块设备,inode->i_zone[0]存放着设备号

        return block_read(inode->i_zone[0],&file->f_pos,buf,count);
    if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {//为目录或常规文件

        if (count+file->f_pos > inode->i_size)
            count = inode->i_size - file->f_pos;
        if (count<=0)
            return 0;
        return file_read(inode,file,buf,count);
    }
    printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);// 否则打印节点文件属性,并返回出错码退出

    return -EINVAL;
}

int sys_write(unsigned int fd,char * buf,int count)//写文件系统调用

{
    struct file * file;
    struct m_inode * inode;
// 如果文件句柄值大于程序最多打开文件数NR_OPEN,或者需要写入的字节计数小于0,或者该句柄 的文件结构指针为空,则返回出错码并退出    

    if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
        return -EINVAL;
    if (!count)
        return 0;
    inode=file->f_inode;// 取文件对应的i 节点

    if (inode->i_pipe)//若是管道文件

        return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
    if (S_ISCHR(inode->i_mode))//为字符设备,inode->i_zone[0]存放着设备号

        return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
    if (S_ISBLK(inode->i_mode))//为块设备,inode->i_zone[0]存放着设备号

        return block_write(inode->i_zone[0],&file->f_pos,buf,count);
    if (S_ISREG(inode->i_mode))//为目录或常规文件

        return file_write(inode,file,buf,count);
    printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);// 否则打印节点文件属性,并返回出错码退出

    return -EINVAL;
}

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

上一篇:char_dev.c

下一篇:open.c

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