[文件系统]read系统调用剖析(二)

来源:互联网 发布:工业机械手控制软件 编辑:程序博客网 时间:2024/06/05 16:09
在vfs_read()函数中有如下几句代码:
291                 if (file->f_op->read)292                         ret = file->f_op->read(file, buf, count, pos);293                 else294                         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()函数进行异步预读。
文件预读取的概念:文件预读取的概念
0 0
原创粉丝点击