Linux0.11内核源码解析-file_dev.c

目录

功能描述

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类似。

Linux0.11内核源码解析-file_dev.c_第1张图片

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 (ii_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);
}

你可能感兴趣的:(linux0.11内核源码,linux,驱动开发)