block: cfq 学习01
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调度器所关系到的队列,一个是同步的,一个是异步的,下面是我根据自己的理解画的一张关系图:

REF
cfq参数: https://www.kernel.org/doc/Documentation/block/cfq-iosched.txt
block: cfq 学习01的更多相关文章
- block:cfq 学习02
From: https://blog.csdn.net/vanbreaker/article/details/8308766 前文介绍了CFQ调度器的一些概念和结构之间的关系,这里再结合实际的代码,来 ...
- Python学习--01入门
Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...
- Java虚拟机JVM学习01 流程概述
Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...
- Android Testing学习01 介绍 测试测什么 测试的类型
Android Testing学习01 介绍 测试测什么 测试的类型 Android 测试 测什么 1.Activity的生命周期事件 应该测试Activity的生命周期事件处理. 如果你的Activ ...
- Java学习01
Java学习01 第一章 1.JRE与JDK JDK(JAVA Develop Kit,JAVA开发工具包)提供了Java的开发环境和运行环境,主要用于开发JAVA程序,面向Java程序的开发者; J ...
- ThinkPhp学习01
原文:ThinkPhp学习01 一.ThinkPHP的介绍 MVC M - Model 模型 工作:负责数据的操作 V - View 视图(模板 ...
- 【iScroll源码学习01】准备阶段 - 叶小钗
[iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文 http://www.cnblogs.com/yexiaochai/p/3 ...
- JVM学习01:内存结构
JVM学习01:内存结构 写在前面:本系列分享主要参考资料是 周志明老师的<深入理解Java虚拟机>第二版. 内存结构知识要点Xmind梳理 案例分析 分析1 package com.h ...
- webservice学习01:wsdl文档结构
webservice学习01:wsdl文档结构 wsdl文档结构 WSDL文档示例 <wsdl:definitions xmlns:xsd="http://www.w3.org/200 ...
随机推荐
- easyUI的treegrid添加节点(append)时间过长,设置等待(wait)遮罩效果
如题所述,在treegrid中,一次添加多个节点时,时间很长,但easyUI并无显示等待信息,让人以为是陷入了死循环,或者死机了,用户体验很差. 本来,treegrid(或者datagrid)有所谓的 ...
- 2015/12/30 字符集 ASCII 到Unicode
——每个软件开发人员应该无条件掌握的知识! ——Unicode伟大的创想! 相信大家一定碰到过,打开某个网页,却显示一堆像乱码,如"бЇЯАзЪСЯ"."�??????? ...
- ResolveUrl in external JavaScript file in asp.net project
https://stackoverflow.com/questions/11263425/page-resolveurl-is-not-working-in-javascript The proble ...
- 【POI】T1 特工 szp
T1 特工szp [问题描述] Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工.Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过 ...
- luogu 2627 修建草坪
题目大意: 一个数列,取出一些数使得它们的总和最大且没有k个连续 思路: 首先我们可以找到一个nk的dp dp方程:dp[i]=dp[i-1]+sum[i]-sum[j] (sum[j]尽量小) 然后 ...
- [Codeforces 496E] Distributing Parts
[题目链接] https://codeforces.com/contest/496/problem/E [算法] 按右端点排序 , 每个乐曲优先选取的左端点最大的演奏家 用std :: set维护贪心 ...
- 2010–2011, NEERC, Northern Subregional C.Commuting Functions
C.Commuting Functions 由于要求答案字典序最小,我们肯定希望从g(1)开始对函数g进行赋值,于是又公式f(g(x))=g(f(x)) 设f(x)=i 我们推导出 由于f是双射,当i ...
- bzoj1407 [Noi2002]Savage——扩展欧几里得
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1407 看到一定有解,而且小于10^6,所以可以枚举: 判断一个解是否可行,就两两判断野人 i ...
- uva11149
Consider an n-by-n matrix A. We define Ak = A ∗ A ∗ . . . ∗ A (k times). Here, ∗ denotes the usual m ...
- 2-4 Vue中的属性绑定和双向数据绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...