linux内核 - io子系统 - 文件io - io调度

背景

  • 在嵌入式平台实现行车记录仪等产品的录像功能(使用SD卡存储)时,性能普通,研究确认IO调度是否能提升性能。

调度说明

  • 在linux平台以普通方式(缓存io)读写文件,读写请求并不是直接发给存储设备处理,操作系统会先将请求(数据和目标等信息)缓存起来,经过算法调度和处理(合并、排序请求)后,再发送请求到存储设备。

为何需要调度算法

  • 磁盘是低速设备,为了加快磁盘读写性能,系统会使用内存作为缓存和缓冲,当内存的读写请求较多时就会引发调度问题。
  1. IO请求较多以及来源(请求发起进程)比较复杂时。
  • 为了保证所有IO请求能够以相对公平的方式得到执行,从而产生的优先级问题。
  • 为了尽可能的提高性能,需要配合缓存机制实现一些优化策略,例如:丢弃重复的请求(两个请求先后写同一block,只需执行后面的请求),取消无必要读写请求(一个请求写,一个请求再读取同样的文件,读操作就可以不必触发磁盘IO,可以直接从缓存中读取),合并相临块操作请求(两个请求读写相邻block,可以合并成一个io请求,减少存储设备请求次数)。
  1. 存储设备特性
  • 机械硬盘的磁头是通过不断旋转来读写数据的,定位数据时,可能出现寻道时间较长的问题,特别是请求操作的磁盘块与磁头移动方向相反时,需要等磁头转完一圈,耗时无法忽视。

调度措施

  1. 请求队列
  • 请求队列对性能影响较大,队列容量越大,可缓存的请求越多,可以进行更好的合并和排序,但是队列越大,写的实时性越差。
/sys/block/[存储设备]/queue/nr_requests
例子:
xxx:$ cat /sys/block/sda/queue/nr_requests
64
  1. IO调度算法通过两种方式来提升性能:合并和排序。
  • 合并:当多个IO请求操作的是相邻的磁盘扇区,那么就将这些请求合并为一个请求,cpu只需要向磁盘发送一个请求指令,减少了请求指令的开销。
  • 排序:将合并处理后的IO请求,根据请求磁盘扇区的顺序,在请求队列中进行排序,使得磁头可以按照磁盘的旋转顺序完成IO请求,可以减少磁盘的寻道次数。

个人总结

  • IO调度适用于IO请求比较多,比较复杂的场景,例如:服务器应用,或者使用机械硬盘的情况下。
  • 在嵌入式平台,IO请求情况比较简单,特别是使用SD卡或者固态硬盘等作为存储设备的情况下,调整调度算法的作用不大。

调度算法

  • 为了满足不同的需求,linux内核支持多种io调度算法。

Noop (No Operation)

  • Noop是内核中最原始、最简单的调度算法,该算法将IO请求放入到一个FIFO队列中,对于一些连续磁盘的IO请求,Noop算法会适当做一些合并,然后逐个执行这些IO请求。
  • 在以下场景中会有一些优势
  1. 如今的存储设备有些比较智能,拥有自己的调度能力可以更好更合适地组织IO请求,不像早期存储设备只能被动的执行IO请求,例如:Raid,SAN,NAS等,不需要IO调度器去做额外的调度工作。
  2. 嵌入式平台固态存储设备。

CFQ(Complete Fair Queuing)

  • CFQ 为每个进程分配一个 I/O请求队列,在每个队列的内部,进行合并和排序的优化,CFQ以轮询的方式处理这些队列,每次从一个队列中处理特定数量的请求(默认为 4个),它试图将 I/O 带宽均匀的分配给每个进程。
  • CFQ 原本针对的是多媒体或桌面应用场景,然而,CFQ在许多场景中内表现的很好; CFQ 对每一个 IO 请求都是公平的。这使得 CFQ很适合离散读的应用 (eg: OLTP DB)。
  • 多数Linux发型版(不仅仅是企业版)选择 CFQ 作为默认的 I/O 调度器。

Deadline

内核相关配置

  1. 查看内核支持的io调度算法
[root@cvitek]~# dmesg | grep -i "io scheduler"
[    1.018721] io scheduler noop registered
[    1.018725] io scheduler deadline registered 
[    1.018752] io scheduler cfq registered (default)
[    1.018756] io scheduler mq-deadline registered
[    1.018759] io scheduler kyber registered
* 说明:加(default)的项表示为默认的io调度算法。
  1. 查看和设置某个块设备使用的调度算法
* 查看
cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
说明: /dev/sda 是一个块设备,带中括号[]的是设备当前使用的调度算法
* 设置
echo cfq > /sys/block/sda/queue/scheduler
  1. 设置内核默认的调度算法
  • 有些嵌入式linux环境下设置不了设备使用的调度算法,所以只能更改默认的调度算法
* 修改内核配置选项
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"

你可能感兴趣的:(#,Linux,内核知识,Linux内核,文件io,IO调度)