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

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

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

在先容直接 I/O 之前,先来先容下直接I/O这种机制发生的缘故起因。事实已经有了缓存I/O(Buffered I/O),那必定可以或许像到缓存I/O有缺陷吧,就凭证这个思绪来。

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

什么是缓存 I/O (Buffered I/O)

缓存 I/O 又被称作尺度 I/O,大大都文件体系的默认 I/O 操纵都是缓存 I/O。在 Linux 的缓存 I/O 机制中,操纵体系会将 I/O 的数据缓存在文件体系的页缓存( page cache )中,也就是说,数据会先被拷贝到操纵体系内核的缓冲区中,然后才会从操纵体系内核的缓冲区拷贝到应用措施的地点空间。写的进程就是数据流反偏向。缓存 I/O 有以下这些利益:

  1. 缓存 I/O 行使了操纵体系内核缓冲区,在必然水平上疏散了应用措施空间和现实的物理装备。
  2. 缓存 I/O 可以镌汰读盘的次数,从而进步机能。

对付读操纵:当应用措施要去读取某块数据的时辰,假如这块数据已经在页缓存中,那就返回之。而不必要颠末硬盘的读取操纵了。假如这块数据不在页缓存中,就必要从硬盘中读取数据到页缓存。

对付写操纵:应用措施会将数据先写到页缓存中,数据是否会被当即写到磁盘,这取决于所回收的写操纵机制:

  • 同步机制,数据会当即被写到磁盘中,直到数据写完,写接谈锋返回;
  • 耽误机制:写接口当即返回,操纵体系会按期地将页缓存中的数据刷到硬盘。以是这个机制会存在丢失数据的风险。想象下写接口返回的时辰,页缓存的数据还没刷到硬盘,正好断电。对付应用措施来说,以为数据已经在硬盘中。

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

缓存I/O的写操纵

缓存 I/O 的弱点

在缓存I/O的机制中,以写操纵为例,数据先从用户态拷贝到内核态中的页缓存中,然后又会从页缓存中写到磁盘中,这些拷贝操纵带来的CPU以及内存的开销长短常大的。

对付某些非凡的应用措施来说,可以或许绕开内核缓冲区可以或许获取更好的机能,这就是直接I/O呈现的意义。

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

直接I/O写操纵

直接I/O 先容

往往通过直接I/O方法举办数据传输,数据直接从用户态地点空间写入到磁盘中,直接跳过内核缓冲区。对付一些应用措施,譬喻:数据库。他们更倾向于本身的缓存机制,这样可以提供更好的缓冲机制进步数据库的读写机能。直接I/O写操纵如上图所示。

直接I/O 计划与实现

要在块装备中执行直接 I/O,历程必需在打开文件的时辰配置对文件的会见模式为 O_DIRECT,这样就便是汇报操纵体系历程在接下来行使 read() 可能 write() 体系挪用去读写文件的时辰行使的是直接 I/O 方法,所传输的数据均不颠末操纵体系内核缓存空间。行使直接 I/O 读写数据必必要留意缓冲区对齐( buffer alignment )以及缓冲区的巨细的题目,即对应 read() 以及 write() 体系挪用的第二个和第三个参数。这里边说的对齐指的是文件体系块巨细的对齐,缓冲区的巨细也必需是该块巨细的整数倍。

下面首要先容三个函数:open(),read() 以及 write()。Linux 中会见文件具有多样性,以是这三个函数对付处理赏罚差异的文件会见方法界说了差异的处理赏罚要领,本文首要先容其与直接 I/O 方法相干的函数与成果.起首,先来看 open() 体系挪用,其函数原型如下所示:

  1. int open(const char *pathname, int oflag, … /*, mode_t mode * / ) ; 

当应用措施必要直接会见文件而不颠末操纵体系页高速缓冲存储器的时辰,它打开文件的时辰必要指定 O_DIRECT 标识符。

操纵体系内核中处理赏罚 open() 体系挪用的内核函数是 sys_open(),sys_open() 会挪用 do_sys_open() 行止理赏罚首要的打开操纵。它首要做了三件工作:

  1. 挪用 getname() 从历程地点空间中读取文件的路径名;
  2. do_sys_open() 挪用 get_unused_fd() 从历程的文件表中找到一个空闲的文件表指针,响应的新文件描写符就存放在当地变量 fd 中;
  3. 函数 do_filp_open() 会按照传入的参数去执行响应的打开操纵。

下面列出了操纵体系内核中处理赏罚 open() 体系挪用的一个首要函数相关图。

  1. sys_open()  
  2.  |-----do_sys_open()  
  3.  |---------getname()  
  4.  |---------get_unused_fd()  
  5.  |---------do_filp_open()  
  6.  |--------nameidata_to_filp()  
  7.  |----------__dentry_open() 

函数 do_flip_open() 在执行的进程中会挪用函数 nameidata_to_filp(),而 nameidata_to_filp() 最终会挪用 __dentry_open() 函数,若历程指定了 O_DIRECT 标识符,则该函数会搜查直接 I./O 操纵是否可以浸染于该文件。下面列出了 __dentry_open() 函数中与直接 I/O 操纵相干的代码。

  1. if (f->f_flags & O_DIRECT) {  
  2.  if (!f->f_mapping->a_ops ||  
  3.  ((!f->f_mapping->a_ops->direct_IO) &&  
  4.  (!f->f_mapping->a_ops->get_xip_page))) {  
  5.  fput(f);  
  6.  f = ERR_PTR(-EINVAL);  
  7.  }  

当文件打开时指定了 O_DIRECT 标识符,那么操纵体系就会知道接下来对文件的读可能写操纵都是要行使直接 I/O 方法的。

(编辑:河北网)

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

热点阅读