浅析 Linux 文件 IO 读写

作者: 光剑书架上的书 | 来源:发表于2021-03-26 00:34 被阅读0次

浅析 Linux 文件 IO 读写

Linux的文件IO子系统是Linux中最复杂的一个子系统(没有之一)。读者可以参考以下这个图:

https://www.thomas-krenn.com/de/wikiDE/images/2/2d/Linux-storage-stack-diagram_v4.0.pdf

Block Layer的运行调度模型

数据从 Page Cache 同步到磁盘上,发出的请求称为一个request,一个request包含一组 bio,每个bio包含要同步的数据pages,你要把Page和磁盘的数据进行同步。

和网络子系统不同,磁盘的调度是有要求的,不是说你发一个page,我就帮你写进去,你再发一个page,我就给你再写一个进去。你要写磁盘的一个地方,磁盘要先把磁头物理上移动到那个轨道上,然后才能写,你让磁头这样移来移去的,磁盘的性能就很难看了。

Linux的IO调度器称为evelator(电梯),因为Linus开始实现这个系统的时候,使用的就是电梯算法。

坐过电梯很容易理解什么是电梯算法,电梯的算法是:电梯总是从一个方向,把人送到有需要的最高的位置,然后反过来,把人送到有需要的最低一个位置。这样效率是最高的,因为电梯不用根据先后顺序,不断调整方向,走更多的冤枉路。

为了实现这个算法,我们需要一个plug的概念。这个概念类似马桶的冲水器,你先把冲水器用塞子堵住,然后开始接水,等水满了,你一次把塞子拔掉,冲水器中的水就一次冲出去了。在真正冲水之前,你就有机会把数据进行合并,排序,保证你的“电梯”可以从一头走到另一头,然后从另一头回来。

我们前面讲IO系统的时候就提过磁盘调度子系统的ftrace跟踪,这里我们深入看看blktrace跟踪到的事件的含义:

请求相关

Q - queued:bio请求进入调度
G - get request:分配request
I - inserted:request进入io调度器

调度相关

B - bounced:硬件无法访问内存,需要把内存降低到硬件可访问
M - back merge:请求和前一个从后面合并
F - front merge:请求和前一个从前面合并
X - split:请求分析为多个request(很可能是因为硬件不支持太大的请求)
A - remap:基于分区等,重新映射request的位置
R - requeue: Request重新回到调度队列
S - sleep:调度器进入休眠P - plug:调度队列插入设备(准备合并)
U - unplug:调度队列离开设备(全部一次写入设备中)
T - unplug due to timer超时,而不是数据足够发起的unplug

发出相关

C - complete:完成一个request的调度(无论成功还是失败)
D - issued:发送到设备,这个是从下层硬件驱动发起的

我们通过对这些事件的跟踪,对照硬件的特性大概就可以知道运行的模型是否正常了。

Block Layer 中的 IO Scheduler 三个调度算法:

  • noop,是 no operation,就是不调度的算法。有什么请求都直接写下去。这通常用于两种情形:你的磁盘是比如SSD那样的内存存储设备,根本不需要调度,往下写就对了。第二种情形是你的磁盘比较高级,自带调度器,OS不需要自作聪明,有什么请求直接往下扔就好了。这两种情况就应该选noop算法。

  • deadline,是一个改良的电梯算法,基本上和电梯算法一样,但加了一条,如果部分请求等太久了(deadline到了,默认读请求500ms,写请求5s),电梯就要立即给我掉头,先处理这个请求。

  • cfg,CPU调度器,完全公平调度器。这个算法按任务分成多个队列,按队列的“完全公平”进行调度。利用这个算法,可以通过ionice设定每个任务不同的优先级,提供给调度器进行分级调度。
    https://zhuanlan.zhihu.com/p/22604682

首先来看一下一般的IO调用。在传统的文件IO操作中,我们都是调用操作系统提供的底层标准IO系统调用函数 read()、write() ,此时调用此函数的进程(在JAVA中即java进程)由当前的用户态切换到内核态,然后OS的内核代码负责将相应的文件数据读取到内核的IO缓冲区,然后再把数据从内核IO缓冲区拷贝到进程的私有地址空间中去,这样便完成了一次IO操作。如下图所示:

注意两点:

  • OS的read函数会在内核IO缓冲区中预读取数据,减少磁盘IO操作。
  • Java的BufferedReader或BufferedInputStream的缓冲区的作用是减少系统调用。

相关文章

  • 浅析 Linux 文件 IO 读写

    浅析 Linux 文件 IO 读写 Linux的文件IO子系统是Linux中最复杂的一个子系统(没有之一)。读者可...

  • 跟我一起学Python(八)

    一、IO编程 读写文件是最常见的IO操作,Python内置了读写文件的函数。文件读写的原理:在磁盘上读写文件的功能...

  • Linux 文件IO 和 标准IO

    [TOC] Linux 文件IO 和 标准IO Linux 文件IO Linux中做文件IO最常用到的5个函数是:...

  • 用Python实现磁盘IO操作全攻略,让数据流动起来!

    01 文件读写 1. 打开文件 读写文件是最常见的IO操作。Python内置了读写文件的函数,方便了文件的IO操作...

  • Node基础

    Node基础 为什么学习Node? IO优势对于文件读写,Node采用的是非阻塞IO传统IO在读写文件的时候CPU...

  • 31.Python:文件读写

    IO操作与读写文件 读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。不论哪种,一定...

  • org.apache.commons.io.FileUtils使

    org.apache.commons.io.FileUtils快速读写文件 其他参考 Commons IO方便读写...

  • Linux编程学习笔记 | Linux IO学习[2] - 标准

    在上一篇Linux编程学习笔记 | Linux IO学习[1] - 文件IO中,我总结了Linux下的文件IO。文...

  • IO流

    1. 了解IO 2. 创建文件 3. 读写文件内容 RandomAccessFile类读写文件 ...

  • IO 文件读写

    流程: 1.打开或者新建立一个文件 2.读/写数据 3.关闭文件 格式: file = open('文件名','模...

网友评论

    本文标题:浅析 Linux 文件 IO 读写

    本文链接:https://www.haomeiwen.com/subject/semdhltx.html