加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 移动互联 > 正文

5分钟搞懂Linux中直接I/O原理

发布时间:2019-06-15 01:10:33 所属栏目:移动互联 来源:源理君头条号
导读:在先容直接 I/O 之前,先来先容下直接I/O这种机制发生的缘故起因。事实已经有了缓存I/O(Buffered I/O),那必定可以或许像到缓存I/O有缺陷吧,就凭证这个思绪来。 什么是缓存 I/O (Buffered I/O) 缓存 I/O 又被称作尺度 I/O,大大都文件体系的默认 I/O 操纵都是缓

下边我们来看一下当历程通过 read() 体系挪用读取一个已经配置了 O_DIRECT 标识符的文件的时辰,体系都做了哪些处理赏罚。 函数 read() 的原型如下所示:

  1. ssize_t read(int feledes, void *buff, size_t nbytes) ; 

操纵体系中处理赏罚 read() 函数的进口函数是 sys_read(),其首要的挪用函数相关图如下:

  1. sys_read()  
  2.  |-----vfs_read()  
  3.  |----generic_file_read()  
  4.  |----generic_file_aio_read()  
  5.  |--------- generic_file_direct_IO() 
  6. ​ 

函数 sys_read() 从历程中获取文件描写符以及文件当前的操纵位置后会挪用 vfs_read() 函数去执行详细的操纵进程,而 vfs_read() 函数最终是挪用了 file 布局中的相干操纵去完成文件的读操纵,即挪用了 generic_file_read() 函数,其代码如下所示:

  1. ssize_t  
  2. generic_file_read(struct file *filp,  
  3. char __user *buf, size_t count, loff_t *ppos)  
  4. {  
  5.  struct iovec local_iov = { .iov_base = buf, .iov_len = count };  
  6.  struct kiocb kiocb;  
  7.  ssize_t ret;  
  8.   
  9.  init_sync_kiocb(&kiocb, filp);  
  10.  ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);  
  11.  if (-EIOCBQUEUED == ret)  
  12.  ret = wait_on_sync_kiocb(&kiocb);  
  13.  return ret;  

函数 generic_file_read() 初始化了 iovec 以及 kiocb 描写符。描写符 iovec 首要是用于存放两个内容:用来吸取所读取数据的用户地点空间缓冲区的地点缓和冲区的巨细;描写符 kiocb 用来跟踪 I/O 操纵的完成状态。之后,函数 generic_file_read() 凋用函数 __generic_file_aio_read()。该函数搜查 iovec 中描写的用户地点空间缓冲区是否可用,接着查看会见模式,若会见模式描写符配置了 O_DIRECT,则执行与直接 I/O 相干的代码。函数 __generic_file_aio_read() 中与直接 I/O 有关的代码如下所示:

  1. if (filp->f_flags & O_DIRECT) {  
  2.  loff_t pos = *ppos, size;  
  3.  struct address_space *mapping;  
  4.  struct inode *inode;  
  5.   
  6.  mapping = filp->f_mapping;  
  7.  inode = mapping->host;  
  8.  retval = 0;  
  9.  if (!count)  
  10.  goto out;  
  11.  size = i_size_read(inode);  
  12.  if (pos < size) {  
  13.  retval = generic_file_direct_IO(READ, iocb,  
  14.  iov, pos, nr_segs);  
  15.  if (retval > 0 && !is_sync_kiocb(iocb))  
  16.  retval = -EIOCBQUEUED;  
  17.  if (retval > 0)  
  18.  *ppos = pos + retval;  
  19.  }  
  20.  file_accessed(filp);  
  21.  goto out;  

上边的代码段首要是搜查了文件指针的值,文件的巨细以及所哀求读取的字节数量等,之后,该函数挪用 generic_file_direct_io(),并将操纵范例 READ,描写符 iocb,描写符 iovec,当前文件指针的值以及在描写符 io_vec 中指定的用户地点空间缓冲区的个数等值作为参数传给它。当 generic_file_direct_io() 函数执行完成,函数 __generic_file_aio_read()会继承执行去完成后续操纵:更新文件指针,配置会见文件 i 节点的时刻戳;这些操纵所有执行完成往后,函数返回。 函数 generic_file_direct_IO() 会用到五个参数,各参数的寄义如下所示:

  1. rw:操纵范例,可所以 READ 可能 WRITE
  2. iocb:指针,指向 kiocb 描写符 
  3. iov:指针,指向 iovec 描写符数组
  4. offset:file 布局偏移量
  5. nr_segs:iov 数组中 iovec 的个数

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读