CFQ,即Completely Fair Queueing绝对公平调度器,力图为竞争块设备使用权的所有进程分配一个等同的时间片,在调度器分配给进程的时间片内,进程可以将其读写请求发送给底层块设备,当进程的时间片消耗完,进程的请求队列将被挂起,等待调度。相对于Noop和Deadline调度器,CFQ要复杂得多,因此可能要分几次才能将其分析完。

优先级

每个进程都会有一个IO优先级,CFQ调度器将会将其作为考虑的因素之一,来确定该进程的请求队列何时可以获取块设备的使用权。IO优先级从高到低可以分为三大类:RT(real time),BE(best try),IDLE(idle),其中RT和BE又可以再划分为8个子优先级。实际上,我们已经知道CFQ调度器的公平是针对于进程而言的,而只有同步请求(read或syn write)才是针对进程而存在的,他们会放入进程自身的请求队列,而所有同优先级的异步请求,无论来自于哪个进程,都会被放入公共的队列,异步请求的队列总共有8(RT)+8(BE)+1(IDLE)=17个。

调度器的结构

CFQ调度器在整个工作过程中所涉及到的结构比较多,我们可以把这些结构分为两类,一类是用来描述调度器本身相关的结构,由于CFQ将进程作为考虑对象,因此另一类结构就是特定于进程的结构,对于这些结构,我们只选择其内部的重要元素进行分析。和调度器相关的数据结构主要有两个,一个是描述调度器的struct cfq_data,一个是描述队列的struct cfq_queue。

struct cfq_data {

struct request_queue *queue;

/*

* rr list of queues with requests and the count of them

*/

struct cfq_rb_root service_tree;

/*

* Each priority tree is sorted by next_request position. These

* trees are used when determining if two or more queues are

* interleaving requests (see cfq_close_cooperator).

*/

struct rb_root prio_trees[CFQ_PRIO_LISTS];

unsigned int busy_queues;

int rq_in_driver[2];

int sync_flight;

/*

* queue-depth detection

*/

int rq_queued;

int hw_tag;

int hw_tag_samples;

int rq_in_driver_peak;

/*

* idle window management

*/

struct timer_list idle_slice_timer;

struct work_struct unplug_work;

struct cfq_queue *active_queue;

struct cfq_io_context *active_cic;

/*

* async queue for each priority case

*/

struct cfq_queue *async_cfqq[2][IOPRIO_BE_NR];

struct cfq_queue *async_idle_cfqq;

sector_t last_position;

/*

* tunables, see top of file

*/

unsigned int cfq_quantum;

unsigned int cfq_fifo_expire[2];

unsigned int cfq_back_penalty;

unsigned int cfq_back_max;

unsigned int cfq_slice[2];

unsigned int cfq_slice_async_rq;

unsigned int cfq_slice_idle;

unsigned int cfq_latency;

struct list_head cic_list;

/*

* Fallback dummy cfqq for extreme OOM conditions

*/

struct cfq_queue oom_cfqq;

unsigned long last_end_sync_rq;

};

queue:指向块设备对应的request_queue

service_tree:所有待调度的队列都被添加进该红黑树,等待调度获取时间片

prio_trees[CFQ_PRIO_LISTS]:对应8个优先级的红黑树,所有优先级类别为RT或BE的进程的同步请求队列,都会根据优先级添加至相应的红黑树

busy_queues:用于计算service_tree中有多少个队列在等待调度

active_queue:指向当前占有块设备的队列

async_cfqq[2][IOPRIO_BE_NR]:对应RT和BE优先级类的16个异步请求队列

async_idle_cfqq:对应优先级类别为IDLE的异步请求队列

cfq_quantum:用于计算在一个队列的时间片内,最多发放多少个请求到底层的块设备

cfq_fifo_expire[2]:同步、异步请求的响应期限时间

cfq_slice[2]:同步、异步请求队列的时间片长度

struct cfq_queue {

/* reference count */

atomic_t ref;

/* various state flags, see below */

unsigned int flags;

/* parent cfq_data */

struct cfq_data *cfqd;

/* service_tree member */

struct rb_node rb_node;

/* service_tree key */

unsigned long rb_key;

/* prio tree member */

struct rb_node p_node;

/* prio tree root we belong to, if any */

struct rb_root *p_root;

/* sorted list of pending requests */

struct rb_root sort_list;

/* if fifo isn't expired, next request to serve */

struct request *next_rq;

/* requests queued in sort_list */

int queued[2];

/* currently allocated requests */

int allocated[2];

/* fifo list of requests in sort_list */

struct list_head fifo;

unsigned long slice_end;

long slice_resid;

unsigned int slice_dispatch;

/* pending metadata requests */

int meta_pending;

/* number of requests that are on the dispatch list or inside driver */

int dispatched;

/* io prio of this group */

unsigned short ioprio, org_ioprio;

unsigned short ioprio_class, org_ioprio_class;

unsigned int seek_samples;

u64 seek_total;

sector_t seek_mean;

sector_t last_request_pos;

unsigned long seeky_start;

pid_t pid;

struct cfq_queue *new_cfqq;

};

cfqd:指向队列所属的cfq_data

rb_node:用于将队列插入service_tree

rb_key:红黑树节点关键值,用于确定队列在service_tree中的位置,该值要综合jiffies,进程的IO优先级等因素进行计算

p_node:用于将队列插入对应优先级的prio_tree

p_root:对应的prio_tree树根

sort_list:组织队列内的请求用的红黑树,按请求的起始扇区进行排序

fifo:组织队列内的请求用的链表头,按请求的响应期限排序

slice_end:指明时间片何时消耗完

slice_dispatch:在时间片内发送的请求数

ioprio:进程的当前IO优先级

相对于进程的结构有struct io_context和struct cfq_io_context。io_context的核心结构是一个基数树,里面组织了进程所访问的所有块设备所对应的cfq_io_context。cfq_io_context中的核心结构是两个队列,也就是进程在一个CFQ调度器所关系到的队列,一个是同步的,一个是异步的,下面是我根据自己的理解画的一张关系图:

这一节暂时就分析道这里了,后面再结合代码来分析CFQ调度器的具体实现

linux 调整i o优先级,Linux I/O Scheduler--CFQ(上)相关推荐

  1. linux如何查看实时优先级,Linux进程优先级系统——设置实时进程优先级

    前言 最近研发的产品出了点小bug,最后查到根本原因是,其中一个进程A使用基于FIFO的实时进程优先级,而另一个进程B是使用普通调度的进程优先级,而A和B两个进程是互相通信的,进程B会被饿死,而进程A ...

  2. linux调整大页内存,Linux 系统如何进行大页面配置

    Linux 系统如何进行大页面配置 3/31/2018 本文内容 在 Linux 中,物理内存是以页为单位来管理的.页的大小为 4096 字节. 1MB 的内存能划分为 256 页: 1GB 则等同于 ...

  3. linux 线程优先级的高低和执行顺序的关系,混乱的Linux内核实时线程优先级

    原标题:混乱的Linux内核实时线程优先级 背景 Linux会把进程分为普通进程和实时进程,普通进程采用CFS之类调度算法,而实时进程则是采用SCHED_FIFO或SCHED_RR. 无论优先级高低, ...

  4. Linux进程中的优先级的理解(PRI 和 NI)

    文章目录 优先级的基本理解 为什么有优先级的概念 查看进程的优先级 对PRI和NI的理解 用top命令更改已存在进程的nice:达到修改进程优先级 总结 优先级的基本理解 cpu资源分配的先后顺序,就 ...

  5. linux命令优先级设置,linux renice命令参数及用法详解(linux修改程序运行优先级命令)...

    linux renice命令参数及用法详解(linux修改程序运行优先级命令) 发布时间:2012-07-21 12:45:32   作者:佚名   我要评论 renice指令可重新调整程序执行的优先 ...

  6. linux分区设置大小,Linux调整磁盘分区大小

    Resize the disk (Linux调整磁盘分区大小) Resize the partition. Run parted: $ parted Show the partition list: ...

  7. Linux线程属性及优先级设置

    Linux线程属性及优先级设置 [原文引自]http://hikesoso2010.spaces.eepw.com.cn/articles/article/item/86413# 线程的属性由pthr ...

  8. Linux调整网卡MAC地址(指令)

    Linux调整网卡MAC地址(指令) 有的时候需要使用欺骗的方法为电脑设置新的mac,比如存在上网网卡限制,或者想要隐藏自己的真实mac地址.这里列举三种修改mac的方法,适用于Debian系的Lin ...

  9. linux提高程序优先级,Linux基础命令---调整程序优先级renice

    renice renice指令可以重新调整程序运行的优先级,可以通过进程id.用户id.组id来修改优先级.修改组的等级,影响组内所有用户的所有进程优先级:修改用户等级,影响该用户的所有进程优先级.除 ...

最新文章

  1. 山东大学计算机学院预推免,山东大学计算机科学与技术学院(专业学位)计算机技术保研...
  2. 通向人工智能产业落地化的道路在哪?
  3. 珠海网络推广浅析该如何高效的提高搜索引擎的抓取频次?
  4. 22种代码味道(Martin Fowler与Kent Beck)
  5. ServletConfig接口
  6. Lex-BERT:超越FLAT的中文NER模型?
  7. API---有意思的API
  8. .sync 修饰符的理解
  9. 初中参观机器人博物馆的作文_展馆导览机器人好不好用?小笨展馆机器人案例...
  10. append 后如何删除_如何在STATA中合并数据文件呢?
  11. 校招生大规模涨薪、再扩招10000人?大厂抢人有多野?
  12. DatabaseDesign数据库设计
  13. 淘宝为什么不该自己做团购
  14. 配置TOMCAT和IIS协同工作
  15. 永久更改打开matlab时工作目录
  16. sigar 获取跨平台服务器信息
  17. 销毁session的三种方式
  18. 石光荣,黑客帝国,社会化网络----社会化网络能否平衡抽象主导的现代生活? (发表于程序员第一期)
  19. mahout第一篇-----Mahout学习路线图
  20. 交通流优化:一种强化学习方法

热门文章

  1. Google开源依赖注入框架-Guice指南
  2. java类比C++的STL库
  3. mysql 按一定条件导出 导出指定库指定表 数据
  4. 高数————思维导图(上岸必备)(微分方程部分)
  5. yml java集合_JAVA 使用 SnakeYAML 解析与序列化 YAML
  6. Subprocess报FileNotFoundError
  7. Qt使用星空图作为窗口背景,点击键盘的WASD控制小飞机在上面移动。
  8. 尼姆游戏(聪明版)python
  9. meta 标签知多少
  10. PHP网站开发中关于META标签的注意事项