CFQ I/O调度算法与公平性保证(不涉及cgroup和组调度策略)
Cfq调度算法旨在保证所用进程的完全公平性,相同的I/O调度周期内,进程被服务的机会是相同的。
CFQ维护了一些列的调度队列cfq_queue,默认为64个,有io需求的进程会绑定到一个cfq_queue,即一个cfq_queue一个时刻只接受一个进程的请求,cfq_queue有一个私有的request红黑树,request红黑树上的节点按照扇区偏移(与当前服务的扇区的偏移)排序,树的根节点为cfq_queue->rb_root,以及按照时间排序的一个链表,头结点为cfq_queue->fifo_list。
Cfq调度算法使用红黑树的方式维护所有的cfq_queue,cfq_queue红黑树是cfq调度算法的核心,也是cfq调度算法公平性的基础,红黑树的根节点保存在每个设备唯一的cfq描述符cfq_data结构中的cfq_rb_root字段中,树上的每一个节点对应一个cfq_queue。
CFQ调度算法运作时,块设备驱动发现设备传输队列request_queue为空时,会调用注册在调度器(elevator)中的回调函数,从cfq的这些cfq_queue中提起请求传输到块设备的传输队列r中,驱动程序再从传输队列中获取request进行处理。
CFQ调度算法会从cfq红黑树上摘取最左边的节点所对应的cfq_queue进行服务,当对此队列的服务完成或者分配的时间片耗尽,则将此队列重新挂载到红黑树上的最右端,并进行重排和颜色调整,以保证cfq_queue的平衡性。这种策略能保证cfq_queue红黑树/调度树上的所有节点都有相同的公平性,即每一个节点在相同的调度周期中被服务的机会是相同的。
Cfq_queue内部的调度,即对一个进程的请求的调度是按照deadline的调度方式。进程新提交的request请求一方面被加入到cfq_queue的按扇区位置排序的sort_list红黑树中,另一方面被加入到按照加入时间排序的fifo链表中。在获取请求提交到传输队列时,先是查看fifo链表中是否有到期的请求,若有则将此请求作为处理的请求对象提交到传输队列,否则从request红黑树上获取一个扇区邻近的请求处理。
CFQ 组调度与blkio.weight
在内核加入了cgroup机制后,对cfq调度的最大的改变就是引入了group schedule的概念,即同属于一个cgroup的进程,从cfq调度的视图来看是属于同一个同一个组,这个组在内核中用cfq_group结构来描述。cfq_group在整个cfq组调度体系中起一个核心的中间层结构,一方面它被挂载到上层的cfq_data的调度红黑树中,另一方面它维护着下层的cfq_queue调度树,此外它也是cfq与blkio子系统的交换结构。
cfq_group是一个per cgroup per device的结构,cfq_group结构