cfq调度是block层最复杂的一个调度器,主要思想是是说每个进程平均享用IO带宽,实现方法是在时间上对进程进行划分,以此达到平均占用IO的目的。带着几个问题去看cfq
1)现在进程来了之后,是插入到某一个队列中去,或者说是进程的IO插入到其中;
2)上面提到的队列是啥子咧?是一个接收BIO的队列?还是一个进程的队列,io_context是啥子?
【电梯中函数的执行的顺序是啥样子的?很重要!】
elv_set_request
#0 elv_set_request (q=0xffff88007c21aa08, rq=0xffff88007c127590, bio=0xffff88007c892000, gfp_mask=37748736) at block/elevator.c:718 #1 0xffffffff81353f00 in __get_request (gfp_mask=<optimized out>, bio=<optimized out>, op_flags=<optimized out>, op=<optimized out>, rl=<optimized out>) at block/blk-core.c:1172 #2 get_request (q=<optimized out>, op=<optimized out>, op_flags=<optimized out>, bio=0xffff88007c892000, gfp_mask=<optimized out>) at block/blk-core.c:1265 #3 0xffffffff813564ae in blk_queue_bio (q=0xffff88007c21aa08, bio=0xffff88007c892000) at block/blk-core.c:1762 #4 0xffffffff81354900 in generic_make_request (bio=0xffff88007c892000) at block/blk-core.c:2062 #5 0xffffffff81354a1e in submit_bio (bio=0xffff88007c21aa08) at block/blk-core.c:2122 #6 0xffffffff811b35e4 in submit_bh_wbc (op=<optimized out>, op_flags=2081584528, bh=0xffff88007c892000, bio_flags=37748736, wbc=<optimized out>) at fs/buffer.c:3101 #7 0xffffffff811b3770 in __block_write_full_page (inode=<optimized out>, page=0xffffea00000821c0, get_block=<optimized out>, wbc=<optimized out>, handler=<optimized out>) at fs/buffer.c:1789 #8 0xffffffff811b3c08 in block_write_full_page (page=0xffffea00000821c0, get_block=0xffffffff811b5c90 <blkdev_get_block>, wbc=<optimized out>) at fs/buffer.c:2977 #9 0xffffffff811b66d8 in blkdev_writepage (page=<optimized out>, wbc=<optimized out>) at fs/block_dev.c:313
cfq中有优先级树,所有的优先级
对于一个磁盘所有的IO,都是放在一棵优先级数里边管理的(即便这些IO来自于不同的进程)
各种tree之间是什么关系,首先,一个进程在每个设备上都有自己的cfq_queue,这个queue里面装这这个进程所有的IO,那么这些IO是怎么整的呢?
每个设备都有自己的cfq_data,在这个结构中,是如何管理进程的这些东西咧
request在哪里管理呢?request在cfq_queue中管理(elv_rb_add 函数)
cfq_resort_rr_list
上面这个函数中把cfqq加入到cfqd中去,分别加入到:service_tree_add 和 cfq_prio_tree_add,这俩是干嘛的呀
到底要插入到哪一棵service tree啊,
所以我们知道了一件事情,所有的cgroup都是通过key=vdisktime插入到该disk全局红黑树中;
每个cgroup中有一颗服务树二维数组[2][3],这棵树里面,每一进程cfq-queue,就插入到这棵服务树里的一棵,其中键值好像是服务的起始时间;
另外cfqd中还维护着一条对于所有IO的优先级树。。。。
现在,一个进程的IO就放在这里了,在各种树里管理着
大致清楚了选择进程的过程,首先会选择cgroup组,然后会从cgroup组中按照优先级选择一个IO下发。
算是比较清楚了吧,现在,oh,my gosh,这个周不是人过的
明天再想一个问题,一个cgroup组里的进程是怎么共享带宽的咧?