/* * linux/fs/file_dev.c * * (C) 1991 Linus Torvalds */
#include <errno.h> #include <fcntl.h>
#include <linux/sched.h> #include <linux/kernel.h> #include <asm/segment.h>
#define MIN(a,b) (((a)<(b))?(a):(b))// 取a,b 中的最小值。
#define MAX(a,b) (((a)>(b))?(a):(b))// 取a,b 中的最大值。
// 文件读函数 - 根据i 节点和文件结构,读设备数据
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) {//由i 节点可以知道设备号,由filp 结构可以知道文件中当前读写指针位置。buf 指定用户态中缓冲区的位置,count 为需要读取的字节数
int left,chars,nr; struct buffer_head * bh;
if ((left=count)<=0)// 若需要读取的字节计数值小于等于零,则返回
return 0; while (left) { if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {//根据i 节点信息取文件数据块block 在设备上对应的逻辑块号,(filp->f_pos)/BLOCK_SIZE)文件当前指针所在的数据块
if (!(bh=bread(inode->i_dev,nr)))//从inode节点指定的设备上读取该nr逻辑块
break; } else bh = NULL; nr = filp->f_pos % BLOCK_SIZE;//计算文件读写指针在数据块中的偏移值nr
chars = MIN( BLOCK_SIZE-nr , left );//本次需要读的字节数
filp->f_pos += chars;//更新文件当前位置
left -= chars;//还有多少没有读的
if (bh) {//读到逻辑号
char * p = nr + bh->b_data;//则将p 指向读出数据块缓冲区中开始读取的位置
while (chars-->0)//并且复制chars 字节到用户缓冲区buf 中
put_fs_byte(*(p++),buf++); brelse(bh); } else {//没读到逻辑号
while (chars-->0)//否则往用户缓冲区中填入chars 个0 值字节
put_fs_byte(0,buf++); } } inode->i_atime = CURRENT_TIME;// 最后访问时间。
return (count-left)?(count-left):-ERROR; } // 文件写函数 - 根据i 节点和文件结构信息,将用户数据写入指定文件中,(只是写入打开文件对应的高速缓冲区,何何进同步,由高速缓冲区管理程序负责)
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) {//由i 节点可以知道设备号,由filp 结构可以知道文件中当前读写指针位置,buf 指定用户态中 缓冲区的位置,count 为需要写入的字节数
off_t pos; int block,c; struct buffer_head * bh; char * p; int i=0;
/* * ok, append may not work when many processes are writing at the same time * but so what. That way leads to madness anyway. */ if (filp->f_flags & O_APPEND)// 如果是要向文件后添加数据,
pos = inode->i_size;//则将文件读写指针移到文件尾部。
else pos = filp->f_pos;//否则就将在文件读写指针处写入
while (i<count) { if (!(block = create_block(inode,pos/BLOCK_SIZE)))// 创建文件数据块pos/BLOCK_SIZE在设备上对应的逻辑块,并返回设备上对应的逻辑块号
break; if (!(bh=bread(inode->i_dev,block)))//从inode节点指定的设备上读取该block逻辑块
break; c = pos % BLOCK_SIZE;// 求出文件读写指针在数据块中的偏移值c
p = c + bh->b_data;//将p 指向读出数据块缓冲区中开始读取的位置
bh->b_dirt = 1;//置该缓冲区已修改标志
c = BLOCK_SIZE-c;//从开始读写位置到块末共可写入c=(BLOCK_SIZE-c)个字节
if (c > count-i) c = count-i;//若c 大于剩余还需写入的字节数(count-i),则此次只需再写入c=(count-i)即可
pos += c;//更新文件当前指针
if (pos > inode->i_size) { inode->i_size = pos;//修改文件大小
inode->i_dirt = 1;//置修改标志
} i += c;//更新子已写的字书节数
while (c-->0) *(p++) = get_fs_byte(buf++);//从用户缓冲区buf 中复制c 个字节到高速缓冲区中p 指向开始的位置处
brelse(bh); } inode->i_mtime = CURRENT_TIME;// 修改时间(自1970.1.1:0 算起,秒)。
if (!(filp->f_flags & O_APPEND)) {// 如果此次操作不是在文件尾添加数据,
filp->f_pos = pos;//则把文件读写指针调整到当前读写位置
inode->i_ctime = CURRENT_TIME;// i 节点自身修改时间。
} return (i?i:-1); }
|