目录
功能描述
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
功能描述
该文件主要是由两个函数file_read()和file_write()组成,提供系统调用函数read()和write()调用,与block_dev.c类似。
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
这段代码是一个文件读取函数,它从给定的文件中读取指定数量的数据并存储到缓冲区中。
代码首先检查要读取的数据量count是否大于0,如果不是,则返回0表示没有读取任何数据。
接下来进入循环,直到读取完指定数量的数据或者遇到错误。在每次循环中,代码会通过
bmap函数将文件位置filp->f_pos映射到相应的磁盘块号nr。然后,它会读取该磁盘块的内容到缓冲区buf中。
代码会计算出当前磁盘块中的偏移量nr和剩余可读取的字符数chars。然后,它会将指针filp->f_pos向前移动chars个字节,并更新剩余字符数left。
如果成功读取到了磁盘块bh非空,则代码会将该磁盘块中的数据逐个字节地复制到缓冲区中,然后释放该磁盘块brelse(bh)。
如果未能读取到磁盘块bh为空,则代码会填充0字节到缓冲区中。
最后,代码会更新文件的访问时间inode->i_atime,然后返回实际读取的数据量count-left,如果有错误发生则返回负数错误代码。
总之,这段代码实现了一个读取文件数据的函数,并将读取到的数据存储到指定的缓冲区中。
int file_read(struct m_inode * inode, struct file * filp, char * buf, int 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))) {
if (!(bh=bread(inode->i_dev,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;//获取指针
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
这段代码是一个文件写入函数,它将给定的数据写入到文件中。
代码首先检查文件打开标志filp->f_flags是否包含O_APPEND标志,如果包含,则将写入位置pos设置为文件的当前大小inode->i_size,否则将写入位置设置为文件指针filp->f_pos的值。
然后进入循环,直到写入完所有数据或者遇到错误。在每次循环中,代码会创建一个新的磁盘块create_block函数用于存储数据,并将该磁盘块读取到缓冲区bh。然后,代码计算出写入位置在磁盘块中的偏移量c和指针p,并将缓冲区标记为已修改bh->b_dirt = 1。
接下来,代码确定实际要写入的字符数c,以防止超出给定数据量count。然后,代码通过增加位置pos来更新写入位置,并在需要时更新文件的大小inode->i_size和修改标记inode->i_dirt = 1)。同时,代码也增加已写入字符数i。
然后,代码使用get_fs_byte函数从给定的数据缓冲区中逐个字节地复制数据到磁盘块中。完成数据复制后,代码释放该磁盘块brelse(bh)。
循环结束后,代码更新文件的修改时间inode->i_mtime。如果文件打开标志不包含O_APPEND标志,则还会更新文件指针filp->f_pos和inode->i_ctime。
最后,函数返回实际写入的字符数i,如果出现错误则返回-1。
总之,这段代码实现了一个将数据写入文件的函数,并根据需要创建新的磁盘块来存储数据,并更新文件的大小和相关属性。
int file_write(struct m_inode * inode, struct file * filp, char * buf, int 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)))
break;
if (!(bh=bread(inode->i_dev,block)))
break;
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (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++);
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME;
}
return (i?i:-1);
}