文件系统2 【访问文件】

  • 访问文件的模式
模式描述
规范模式规范模式下文件打开后, 标志O_SYNC与 O_DIRECT清0, 而且它的内容是由系统调用read()和write()来存取.系统调用read()将阻塞调用进程,直到数据被拷贝进用户态地址空间.但系统调用write()不同,它在数据被拷贝到高速缓存(延迟写)后就马上结束
同步模式同步模式下文件打开后, 标志O_SYNC置1或稍后由系统调用fcntl对其置1. 这个标志只影响写操作(读操作总是会阻塞),它将阻塞调用进程,直到数据被有效地写入磁盘.
异步模式异步模式下, 文件的访问可以有两种方法, 即通过一组POSIX API或Linux特有的系统调用来实现. 所谓异步模式就是数据传送请求并不阻塞调用进程,而是在后台执行,同时应用程序继续它的正常运行.
内存映射模式内存映射模式下文件打开后,应用程序发出系统调用mmap()将文件映射到内存中. 因此, 文件就成为RAM中的一个字节数组, 应用程序就可以直接访问数组元素, 而不需要用系统调用read(), write()或lseek().
直接I/O模式直接I/O模式下文件打开后,标志O_DIRECT置1.任何读写操作都将数据在用户态地址空间与磁盘间直接传送而不通过页高速缓存.
  • 数据结构
    | 成员 | 描述 |
    |–|--|
    | struct kiocb | |
    | struct iovec | |

  • struct kiocb
    | 成员 | 描述 |
    |–|--|
    | int (*ki_cancel)(struct kiocb *, struct io_event *); | |
    | ssize_t (*ki_retry)(struct kiocb *); | |
    | void (*ki_dtor)(struct kiocb *); | |

  • struct iovec
    | | |
    |–|--|
    | void __user *iov_base; | |
    | __kernel_size_t iov_len; | |

  • 读文件

ssize_t
generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
	struct iovec local_iov = { .iov_base = buf, .iov_len = count };
	struct kiocb kiocb;
	ssize_t ret;

	init_sync_kiocb(&kiocb, filp);
	ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
	if (-EIOCBQUEUED == ret)
		ret = wait_on_sync_kiocb(&kiocb);
	return ret;
}

ssize_t
__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
		unsigned long nr_segs, loff_t *ppos)
{
	struct file *filp = iocb->ki_filp;
	ssize_t retval;
	unsigned long seg;
	size_t count;

	count = 0;
	for (seg = 0; seg < nr_segs; seg++) {
		const struct iovec *iv = &iov[seg];

		/*
		 * If any segment has a negative length, or the cumulative
		 * length ever wraps negative then return -EINVAL.
		 */
		count += iv->iov_len;
		if (unlikely((ssize_t)(count|iv->iov_len) < 0))
			return -EINVAL;
		if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len))
			continue;
		if (seg == 0)
			return -EFAULT;
		nr_segs = seg;
		count -= iv->iov_len;	/* This segment is no good */
		break;
	}

	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
	if (filp->f_flags & O_DIRECT) {
		loff_t pos = *ppos, size;
		struct address_space *mapping;
		struct inode *inode;

		mapping = filp->f_mapping;
		inode = mapping->host;
		retval = 0;
		if (!count)
			goto out; /* skip atime */
		size = i_size_read(inode);
		if (pos < size) {
			retval = generic_file_direct_IO(READ, iocb,
						iov, pos, nr_segs);
			if (retval >= 0 && !is_sync_kiocb(iocb))
				retval = -EIOCBQUEUED;
			if (retval > 0)
				*ppos = pos + retval;
		}
		file_accessed(filp);
		goto out;
	}

	retval = 0;
	if (count) {
		for (seg = 0; seg < nr_segs; seg++) {
			read_descriptor_t desc;

			desc.written = 0;
			desc.arg.buf = iov[seg].iov_base;
			desc.count = iov[seg].iov_len;
			if (desc.count == 0)
				continue;
			desc.error = 0;
			do_generic_file_read(filp,ppos,&desc,file_read_actor);
			retval += desc.written;
			if (!retval) {
				retval = desc.error;
				break;
			}
		}
	}
out:
	return retval;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值