《存储IO路径》专题:不同IO调度器的差异

news2025/1/17 13:50:40

在计算机世界中,有一个神秘的王国,叫做IO王国。这个王国里有四种奇怪的生物,它们分别是Noop调度器、Anticipatory调度器、Deadline调度器和CFQ调度器。IO调度器负责管理计算机中的IO请求,确保它们有序地通过。就像一个交警会根据车流量来指挥交通一样,IO调度器也会根据IO请求的到达顺序来决定处理它们的顺序。

Noop调度器是IO王国的小学生,它非常乖巧,总是按照规矩排队。它的行为非常简单,只会按照IO请求的到达顺序进行处理。有一天,一个叫SSD的小朋友来到IO王国,它想要成为Noop调度器的好朋友。但是,Noop调度器却觉得SSD小朋友不够聪明,因为SSD小朋友不需要排队,可以直接进入王国。于是,Noop调度器就拒绝了SSD小朋友的请求。但是,SSD小朋友并不气馁,它决定要找到一个更聪明的调度器来和它做朋友。

Anticipatory调度器是IO王国的小聪明,它能够预测未来的IO请求。有一天,一个叫Web服务器的小朋友来到IO王国,它想要成为Anticipatory调度器的好朋友。但是,Anticipatory调度器却觉得Web服务器小朋友的请求太简单了,因为它只能处理GET和POST请求。于是,Anticipatory调度器就拒绝了Web服务器小朋友的请求。但是,Web服务器小朋友并不气馁,它决定要找到一个能够理解它请求的调度器来和它做朋友。

Deadline调度器是IO王国的小严格,它要求每个IO作业都要按时完成任务。有一天,一个叫文件服务器的小朋友来到IO王国,它想要成为Deadline调度器的好朋友。但是,Deadline调度器却觉得文件服务器小朋友的请求太慢了,因为它需要很长时间才能完成任务。于是,Deadline调度器就拒绝了文件服务器小朋友的请求。但是,文件服务器小朋友并不气馁,它决定要找到一个能够理解它请求的调度器来和它做朋友。

CFQ调度器是IO王国的小公平,它是一个公平的裁判,确保每个进程都能得到平等的待遇。有一天,一个叫桌面多任务的小朋友来到IO王国,它想要成为CFQ调度器的好朋友。但是,CFQ调度器却觉得桌面多任务小朋友的请求太复杂了,因为它需要同时处理多个任务。于是,CFQ调度器就拒绝了桌面多任务小朋友的请求。但是,桌面多任务小朋友并不气馁,它决定要找到一个能够理解它请求的调度器来和它做朋友。

这四个调度器都有自己的特点,各有优缺点。在选择合适的调度器时,我们要根据具体情况来考虑,是乖巧的SSD、聪明的Web服务器、严格的文件服务器还是公平的桌面多任务系统。不管怎样,这些调度器都在用自己的方式维护着计算机的IO秩序,确保IO请求有序地处理。

接下来,结合代码来对比几种调度器的差异

  1. Noop IO调度器

Noop调度器是一个简单的调度器,它按照请求到达的顺序服务I/O请求。它的实现比较简单,适用于一些简单的存储设备。以下是Noop调度器的代码实现:

struct request_queue {  
    struct request *requests;  
    int head;  
    int tail;  
};  
  
void enqueue_request(struct request_queue *queue, struct request *req) {  
    queue->requests[queue->tail] = *req;  
    queue->tail = (queue->tail + 1) % MAX_REQUESTS;  
}  
  
struct request *dequeue_request(struct request_queue *queue) {  
    return &queue->requests[queue->head];  
}  
  
void noop_schedule(struct request_queue *queue) {  
    struct request *req;  
    while ((req = dequeue_request(queue)) != NULL) {  
        // 处理请求  
    }  
}
  1. Anticipatory IO调度器

Anticipatory调度器是一个基于预计执行时间的调度器,它根据每个I/O作业的预计执行时间来决定服务顺序。它认为一些I/O作业可能会引起其他相关作业的访问,因此它会在预计执行时间更短的作业之前先服务一些其他相关作业。以下是Anticipatory调度器的代码实现:

struct job {  
    int sector;  
    int arrival_time;  
    int service_time;  
};  
  
struct job_queue {  
    struct job *jobs;  
    int head;  
    int tail;  
};  
  
void enqueue_job(struct job_queue *queue, struct job *job) {  
    queue->jobs[queue->tail] = *job;  
    queue->tail = (queue->tail + 1) % MAX_JOBS;  
}  
  
struct job *dequeue_job(struct job_queue *queue) {  
    return &queue->jobs[queue->head];  
}  
  
void anticipatory_schedule(struct job_queue *queue) {  
    struct job *job;  
    while ((job = dequeue_job(queue)) != NULL) {  
        // 处理请求  
    }  
}
  1. Deadline IO调度器

Deadline调度器是一个具有超时时间的调度器,它为每个I/O作业设定一个超时时间。如果某个I/O作业等待时间超过了设定的超时时间,那么它会被优先服务。以下是Deadline调度器的代码实现:

struct request {  
    int sector;  
    int queue_num;  
    int arrival_time;  
};  
  
struct request_queue {  
    struct request *requests;  
    int head;  
    int tail;  
};  
  
void enqueue_request(struct request_queue *queue, struct request *req) {  
    queue->requests[queue->tail] = *req;  
    queue->tail = (queue->tail + 1) % MAX_REQUESTS;  
}  
  
struct request *dequeue_request(struct request_queue *queue) {  
    return &queue->requests[queue->head];  
}  
  
void deadline_schedule(struct request_queue *queue) {  
    struct request *req;  
    while ((req = dequeue_request(queue)) != NULL) {  
        // 处理请求  
    }  
}

4.CFQ调度器

CFQ调度器是一种通用型的I/O调度算法,旨在为所有进程提供公平的I/O带宽。它是Linux内核中使用最广泛的调度器之一,并且在许多操作系统中都有实现。

CFQ调度器通过为每个进程创建一个I/O队列来实现公平的I/O分配。每个进程的队列都是一个先进先出(FIFO)的队列,其中包含了该进程的I/O请求。当一个进程的I/O请求到达时,它会被添加到该进程的队列中,等待服务。

在CFQ调度器中,每个进程的I/O带宽是按照其进程优先级和等待时间来分配的。调度器会根据进程的优先级和等待时间来决定服务哪个进程的I/O请求。如果两个进程的优先级和等待时间相同,那么调度器会按照先来先服务的原则进行处理。

下面是一个简单的CFQ调度器的代码实现,供参考:

struct cfq_io_data {  
    struct io_queue *queue;  
    struct io_priority_data prio;  
    unsigned long last_end_time;  
    s64 slice;  
    enum class_type type;  
    void *problem_data;  
};  
  
static void cfq_dequeue_request(struct cfq_io_data *io_data)  
{  
    struct io_request *rq = dequeue_next(&io_data->queue->queue);  
    if (!rq)  
        return;  
    cfq_update_io_dispatch(cfqd, cfq_prio_to_weight(&io_data->prio));  
}  
  
static void cfq_dispatch_request(struct cfq_io_data *io_data)  
{  
    struct cfq_data *cfqd = &io_data->queue->cfqd;  
    struct io_request *rq = dequeue_next(&io_data->queue->queue);  
    if (!rq)  
        return;  
    cfq_change_class_weight(&io_data->prio, cfq_classify(rq));  
    cfq_update_io_dispatch(cfqd, cfq_prio_to_weight(&io_data->prio));  
}

上述代码中,cfq_dequeue_request()函数从当前进程的队列中取出下一个I/O请求,而cfq_dispatch_request()函数则根据当前进程的队列中的I/O请求来更新I/O调度器的权重。这些权重将用于决定服务哪个进程的I/O请求。

CFQ调度器通过公平地分配I/O带宽,使得所有进程都能够获得公平的I/O服务。这种公平性对于多任务操作系统来说非常重要,可以避免某些进程因为得不到足够的I/O资源而出现性能问题。同时,CFQ调度器的实现也比较简单和高效,因此在许多系统中都得到了广泛的应用。

在Linux内核中,修改IO调度的算法也比较简单,简单例子参考:

1.查看当前调度算法是NOOP
$ cat /sys/block/nvme0n1/queue/scheduler
[noop] deadline cfq

2.将NOOP算法调整为CFQ
$ echo 'cfq'>/sys/block/nvme0n1/queue/scheduler

3.查看修改后的算法为CFQ
$ cat /sys/block/nvme0n1/queue/scheduler
noop deadline [cfq]

不同的调度器,在不同类型的存储设备上的性能和使用场景都有一定的差异:

  1. Noop调度器:
    • 性能表现:Noop调度器是一个简单的调度程序,它本质上是一个链表实现的FIFO队列,对请求进行简单的合并处理。由于它的实现简单,因此在各种类型的存储设备上性能表现相对较差。
    • 使用场景:Noop调度器适用于固态硬盘(SSD)等存储设备,因为固态硬盘的IO调度算法越简单,效率就越高。
  1. Anticipatory调度器:
    • 性能表现:Anticipatory调度器通过预测未来的IO请求,将硬盘的I/O请求预先发送到硬盘中,以减少磁头的移动和寻道时间,提高整体性能。它在处理有一定数据量但IO压力不是非常大的场景中表现最为出色。
    • 使用场景:Anticipatory调度器适用于机械硬盘(HDD)和SATA SSD等存储设备,因为在这些存储设备上,提高效率需要考虑寻道时间和磁头移动等因素。
  1. Deadline调度器:
    • 性能表现:Deadline调度器以减少磁头的移动和寻道时间为目标,尽可能地满足I/O请求的截止期限。它适合用在有大量I/O请求并且IO压力比较重的业务,比如数据库系统。
    • 使用场景:Deadline调度器适用于机械硬盘(HDD)和SATA SSD等存储设备,因为在这些存储设备上,提高效率需要考虑寻道时间和磁头移动等因素。对于业务比较单一并且IO压力比较重的业务,Deadline调度器是最佳的选择。
  1. CFQ调度器:
    • 性能表现:CFQ调度器是一种通用的调度算法,它以进程为出发点考虑,保证所有进程都能公平地分配到I/O资源。它适合用于多任务、多媒体等需要公平分配I/O资源的场景中。
    • 使用场景:CFQ调度器适用于机械硬盘(HDD)、SATA SSD和NVMe SSD等存储设备。然而,由于CFQ调度器的复杂度较高,因此在固态硬盘这种场景下,其效率可能会比Noop和Anticipatory调度器低。

综上所述,不同类型的调度器在不同的存储设备上表现会有所差异。在选择合适的调度器时,需要根据具体的存储设备类型和使用场景来考虑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/980327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.3 【MySQL】字符集和比较规则的应用

3.3.1 各级别的字符集和比较规则 MySQL 有4个级别的字符集和比较规则,分别是: 服务器级别 数据库级别 表级别 列级别 3.3.1.1 服务器级别 MySQL 提供了两个系统变量来表示服务器级别的字符集和比较规则: 系统变量 描述 character_se…

VIRTIO-BLK代码分析(4)VIRTIO设备中断的注入

VIRTIO设备中断包括vq中断和config中断。Vq中断用于通知Guest已完成数据的处理,虚拟机中可以完成IO请求。Vq中断的模拟是通过irqfd实现的,它将虚拟机中断与irqfd关联上(KVM_SET_GSI_ROUTING和KVM_IRQFD),当虚拟机中访问…

Centos7设置设置时间与windows同步

CentOS7设置时间与windows同步 使用ntp使CentOS服务器的系统时间与机器时间同步于windows服务器centOS机器安装ntpwindows安装ntp同步时间 使用ntp使CentOS服务器的系统时间与机器时间同步于windows服务器 思路是将windows服务器作为ntp服务端,centOS服务器作为ntp…

border-image和border-radius一起使用border-radius不起作用

关于border-image和border-radius一起使用border-radius不起作用 解决方案:最外层父盒子假如叫A添加 background为border-image的值,以及添加 boder-radius。 再添加一层父盒子假如叫B 添加padding值为border的宽度。 C和D都是子盒子 单独设置其border-…

展厅显示大屏怎么选,展厅使用哪种显示大屏好?

近年来,随着信息化科技快速发展,越来越多的企事业单位的展厅都会采用显示大屏来展现各种信息。那么,展厅显示大屏怎么选,哪种显示大屏更好?接下来,小灰从专业角度,用通俗易懂的文字为大家逐一分…

视频集中存储/云存储/磁盘阵列EasyCVR平台分组批量绑定/取消设备功能详解

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台视频能力丰富灵活,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备传…

打造低碳社区,践行环保理念

在城市内推行低碳经济,实现城市的低碳排放,甚至是零碳排放。而社区的结构是城市结构的细胞,社区结构与密度对城市能源及二氧化碳排放起了关键的作用。所以要想实现低碳城市建设,改变原有能源结构,改造低碳社区是第一大…

第 2 章 线性表 (线性表的单链表存储结构实现)

1. 背景说明 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H/* 函数结果状态码 */ #define TRUE 1 /* 返回值为真 */ #define FALSE 0 /* 返回值为假 */ #define RET_OK 0 /* 返回值正确 */ #d…

武汉凯迪正大—接触电阻测试仪器

一、凯迪正大智能回路电阻测试仪产品概述 KDHL-100A操作面板采用人体工学设计,符合操作习惯,采用高频开关电源和数字电路技术,适用于开关控制设备回路电阻的测量。测试电流采用国家标准推荐的直流100A。可在直流100A的情况下直接测得回路电阻…

图像色彩空间的改变

图像色彩空间的改变 OpenCV中有150多种颜鱼空间转换方法。 最广泛使用的转换方法有两种, BGR →Gray 和 BGR→HSV。 cv.cvtColor(input_image,flag) 参数: input_image:进行颜色空间转换的图像. flag:转换类型 cv.COLOR_BGR2GRAY : BGR → GRAY cv.…

恒运资本:沪指震荡跌0.34%,医药、酿酒等板块走低,光刻胶概念等活跃

6日早盘,两市股指再度走低,创业板指跌近1%;成交额有所下降,北向资金小幅净流出。 到午间收盘,沪指跌0.34%报3143.62点,深成指跌0.68%,创业板指跌0.89%,上证50指数跌0.51%&#xff1…

运行Android Automotive模拟器

在windows系统中安装MobaXterm MobaXterm free Xserver and tabbed SSH client for Windows 运行MobaXterm,在宿主机中进入编译后的源码根目录并执行如下命令,若未编译,请参照如下链接,编译车机模拟器Android Automotive编译_IT…

Linux之DNS域名解析服务

目录 Linux之DNS域名解析服务 概述 产生原因 作用 连接方式 因特网的域名结构 拓扑 分类 域名服务器类型 ​编辑 DNS域名解析过程 分类 解析图 搭建DNS域名解析服务器 概述 安装软件 bind服务中三个关键文件 主配置文件分析 一般需要修改三部分:…

ubuntu 20.04 设置 authorized_keys 让 VS Code ssh 远程免密连接

相关文章 VSCode SSH 连接远程ubuntu Linux 主机 前言 前面记录了 VS Code 可以通过 SSH 远程连接 ubuntu Linux 主机,比如代码放在远程 ubuntu 主机上, windows 端 VS Code 通过 ssh 远程连接 ubuntu,并打开 远程主机上的 代码 如果不设置…

手游折扣平台app排行,打折手游平台排行

随着手游市场的不断发展,出现了越来越多的手游折扣平台。在这些平台中,有些提供各种各样的手机游戏,并提供丰厚的福利。本文将向您介绍手游折扣平台app排行,打折手游平台排行。对于目前的游戏来说,无非是哪里玩更划算&…

Eclipse安装及配置tomcat

1.Eclipse安装 1.java -version检查一下有没有jdk 如没有则下载 下载路径:https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 2.Eclipse下载链接:https://www.eclipse.org/downloads/ 3.安装完之后就启动你会看见一个欢迎页面&am…

网络电视盒子哪个好?数码老贾横评整理电视盒子推荐

大家好,我是老贾,今天测评的主题是网络电视盒子哪个好,为让结果更加真实客观,我购入了市面上最热销的12款电视盒子,花费14天时间详细对比芯片、内存、用料、系统、广告等等方面,最终整理了五款表现最佳的电…

摘要-签名-PKI-访问控制-DOS-欺骗技术

摘要-签名-PKI-访问控制-DOS-欺骗技术 信息摘要数字签名 信息摘要 信息摘要通过哈希函数生成的 信息摘要保证数据的完整性 MD5 和 SHA-1 数字签名 唯一确定发送方 基于非对称加密技术(公钥和私钥技术)

Android Framework——进程间通讯学习,从Binder使用看起

前言 Binder 是安卓中非常重要的进程间通讯工具,通过Binder 安卓在ServiceManager中对外提供了一系列的服务。学习Binder,将很好地为我们学习framework开个好头。 Android 使用多进程 Android 开启进程方式很简单,在AndoridMenifest中给四…

ubuntu server 更改时区:上海

1. 打开终端,在命令行中以超级用户或具有sudo权限的用户身份运行以下命令: sudo dpkg-reconfigure tzdata 这会打开一个对话框,用于选择系统的时区设置。 2. 在对话框中,使用上下箭头键在地区列表中选择"Asia"&#x…