linux 0.11 内核学习 -- read_write.c

/*

 * 该文件实现系统调用read,write和lseek。

 */

/*

 *  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);

 

/* 重定位文件读写指针系统调用函数,参数fd是文件句柄,offset是新的文件 */

/* 读写偏移量,origin是偏移的起始地址,可能是下面的三个值:SEEK_SET   */

/* 文件的开始处,SEEK_CUR当前的读写位置,SEEK_END文件结尾处           */

int sys_lseek(unsigned int fd,off_t offset, int origin)

{

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;

// 如果文件对应的i 节点是管道节点,则返回出错码,退出

if (file->f_inode->i_pipe)

return -ESPIPE;

switch (origin) {

case 0: // SEEK_SET

// 若偏移值小于零,则出错

if (offset<0) return -EINVAL;

// 设置文件读写指针等于offset

file->f_pos=offset;

break;

case 1: // SEEK_CUR

if (file->f_pos+offset<0) return -EINVAL;

// 在当前读写指针上加上偏移值

file->f_pos += offset;

break;

case 2: // SEEK_END

if ((tmp=file->f_inode->i_size+offset) < 0)

return -EINVAL;

file->f_pos = tmp;

break;

default: // origin 设置出错

return -EINVAL;

}

 

// 返回重定位后的文件读写指针值

return file->f_pos;

}

 

/* 读文件系统调用函数,参数fd是文件句柄,buf用户缓冲区,count是预读的字节数 */

/* 函数返回的是实际读写的字节数    */

int sys_read(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;

// 若需读取的字节数count 等于0,则返回0

if (!count)

return 0;

// 验证存放数据的缓冲区内存限制

verify_area(buf,count);

// 取文件对应的i 节点

inode = file->f_inode;

// 若是管道文件,并且是读管道文件模式,则进行读管道操作

if (inode->i_pipe)

return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;

// // 如果是字符型文件,则进行读字符设备操作,返回读取的字符数

if (S_ISCHR(inode->i_mode))

return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);

// 如果是块设备文件,则执行块设备读操作,并返回读取的字节数

if (S_ISBLK(inode->i_mode))

return block_read(inode->i_zone[0],&file->f_pos,buf,count);

// 如果是目录文件或者是常规文件

if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) 

{

// 首先验证读取数count 的有效性并进行调整

if (count+file->f_pos > inode->i_size)

// 重新设置读取字节数为文件长度-当前读写指针值

count = inode->i_size - file->f_pos;

if (count<=0)

return 0;

// 设置完count后,调用函数执行文件读操作

return file_read(inode,file,buf,count);

}

// 否则打印节点文件属性,并返回出错码退出

printk("(Read)inode->i_mode=%06o/n/r",inode->i_mode);

return -EINVAL;

}

 

/* 系统调用,实现write系统调用 */

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;

// 若需读取的字节数count 等于0,则返回0

if (!count)

return 0;

// 取文件对应的i 节点。若是管道文件,并且是写管道文件模式,则进行写管道操作

inode=file->f_inode;

if (inode->i_pipe)

return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;

// 如果是字符型文件,则进行写字符设备操作,返回写入的字符数

if (S_ISCHR(inode->i_mode))

return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);

// 如果是块设备文件,则进行块设备写操作,并返回写入的字节数

if (S_ISBLK(inode->i_mode))

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;

}

参考《linux内核完全注释》和网上相关资料

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值