在vfs_read()函数中有如下几句代码:
答:是在各个文件系统mount的时候inode初始化的时候赋值的,比如fat文件系统对应的赋值的位置是kernel/fs/fat/Inode.c文件的fat_fill_inode()函数,即:inode->i_fop = &fat_file_operations;
文件预读取的概念: 文件预读取的概念
291 if (file->f_op->read)
292 ret = file->f_op->read(file, buf, count, pos);
293 else
294 ret = do_sync_read(file, buf, count, pos);
file->f_op->read()函数在哪里赋值的?
答:是在各个文件系统mount的时候inode初始化的时候赋值的,比如fat文件系统对应的赋值的位置是kernel/fs/fat/Inode.c文件的fat_fill_inode()函数,即:inode->i_fop = &fat_file_operations;
154 const struct file_operations fat_file_operations = {
155 .llseek = generic_file_llseek,
156 .read = do_sync_read,
157 .write = do_sync_write,
158 .aio_read = generic_file_aio_read,
159 .aio_write = generic_file_aio_write,
160 .mmap = generic_file_mmap,
161 .release = fat_file_release,
162 .ioctl = fat_generic_ioctl,
163 .fsync = fat_file_fsync,
164 .splice_read = generic_file_splice_read,
165 };
最后vfs_read()函数最终会调用到do_sync_read()函数,
252 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
253 {
254 struct iovec iov = { .iov_base = buf, .iov_len = len };
255 struct kiocb kiocb;
256 ssize_t ret;
257
258 init_sync_kiocb(&kiocb, filp);
259 kiocb.ki_pos = *ppos;
260 kiocb.ki_left = len;
261
262 for (;;) {
263 ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
264 if (ret != -EIOCBRETRY)
265 break;
266 wait_on_retry_sync_kiocb(&kiocb);
267 }
268
269 if (-EIOCBQUEUED == ret)
270 ret = wait_on_sync_kiocb(&kiocb);
271 *ppos = kiocb.ki_pos;
272 return ret;
273 }
filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos)最终最调用到generic_file_aio_read()函数generic_file_aio_read()函数根据上层open()的时候是否带O_DIRECT flag然后进入不同的分支,如果带O_DIRECT flag则表明是直接IO读取操作,不带page cache的缓冲区。如果不带O_DIRECT flag则最终会执行到do_generic_file_read()函数,do_generic_file_read()函数首先到filp->mapping的空间所要读取的页,如果没有找到对应的page,那么会调用page_cache_sync_readahead()函数启用同步预读,如果在文件的address_space找到对应的page则调用page_cache_async_readahead()函数进行异步预读。
文件预读取的概念: 文件预读取的概念