内核回写框架

ULK介绍回写时说得无比复杂,六七年过去了,回写框架完全变了样。每个块设备与bdi相关,每个bdi则对这个块设备负责。


回写的动机: 不想让各种cache在内存中停留太久,以免突然断电致使更新没有反映到硬件上; 不想让cache占用过多的内存,当cache慢慢变大,要时不时把某些东西写回磁盘,当内存不够用时,直接把cache丢掉就行。


这两个动机应该可以统一起来,但我现在还想不出很优雅的总结。表面上看起来,两者互补,但实际上需不需要做此区分呢?即,一个动机能否覆盖另一个动机的功能?


据说linux最早是用两种线程来实现这两个需求,后来又合并为一个了。这个说法现在应该还是成立。但以前的线程要总管全局,现在bdi各管各的。


系统初始化的时候会注册一个默认bdi。注册代码发现现在注册的默认bdi,便为其起一个特殊线程。这个线程基本没负责回写(其实还是要关心一点,但占它功能的比重不大),而不是停遍历已注册bdi,掌管他的回写线程的生死。如果某个bdi上脏东西多了,又没有回写线程,它便为其创造一个。如果某个bdi什么脏东西也没有,又有回写线程,而且线程已经很久没活动了,它便将其杀死。当然,如果是其它情况的话,它就不需要做什么了。这个默认线程最主要的任务便是如此。每隔一段时间它就会醒来做这些事,其间则一直处于沉睡状态。


其余的bdi线程的工作,则不断执行着上层文件系统交下来的任务,以及负责之前所说我们对回写的需求。这种表述很奇怪,仿佛我们最终的需要是次要的,反倒上层文件系统交的任务是主要的。如果我们很好解决了之前所提需求,上层文件系统还有什么可抱怨,有什么其它的任务呢?今天不早了,以后再看看。


总之,一般bdi线程会不停的迭代。一次迭代的内容是:执行上层文件系统交下的任务; 满足我们对回写的需求。每次迭代完以后,线程会判断继需不需要下一次迭代。如果检测到上层文件系统交下的新任务,则进行新一轮迭代(执行新任务,另外顺便执行两个特殊任务)。如果不需继续迭代,则安排睡眠,这时也要看现在是否有脏东西。有,设置一个定时器,一段时间后再来处理:这显然是针对第一个动机。没有,一直睡到被人叫醒。第二个动机,理论上来说,应该要在cache占内存比重超过某个比率时唤醒bdi线程,但线程自身没安排什么,在系统其它地方可能会做类似安排,显式唤醒线程的代码也确实存在。不知还有没有其他需要显示唤醒的需求。


上层文件系统交下来的任务,与实现两个动机的任务,都是同一种抽象。这种任务的抽象最主要的属性是,想要回写多少页。另一个重要属性是,这个任务是什么性质。比如定时回写与防止cache占内存比重过大回写这两个任务在抽象中都有专门安排。于是,bdi的一次迭代中就是在不停处理一些抽象的任务:上层交下来的与满足两个动机的。一个任务完了再处理另一个。可什么叫一个任务完了呢?这个定义根据任务属性不同而不同。


如果是一般任务,任务完成就是回写完指定的页。


如果是定时回写,任务完成的定义类似:保证某个时刻前脏页都已回写。这个的实现是通过指定回写页数与制约回写页条件:只回写在某一时刻之前弄脏的页。


如果是防止缓存占存比重过大的回写,任务完成就是缓存占内存的比例降到某个阀值以下。


当然,如果本身就没什么脏东西要处理,任务自然也算结束了。另外,执行后两个任务时,如果发瑞有上层交下来的任务,则当前任务提前结束。下次迭代便处理这样任务。这样上层的任务有较高优先级。如果抛开上层的任务,线程的使命就太简单了,完成两个特殊任务即可。这时它的工作流程可描述为,每一次活动时,便把一段时间未回写的缓存写回磁盘,如果检测到缓存在内存比太大,则进行回写将比值降下来。做完这些后,如果有脏页,便设定定时器,睡眠(针对动机一)。不然,睡到被人叫醒。(没有针对动机二,但在其它地方,如果发现动机二的问题则将其唤醒)。可见,上层文件系统交下来的任务把整个过程搞混乱了。说了这么多,越来越想知道上层为什么会要求显式回写。最容易想到的理由是显式同步。再说。


至于回写的流程,说起来还挺讲究,简化来说,遍历挂在这个bdi上的脏inode,将其缓存页写回磁盘,再将inode本身写回磁盘。复杂的地方是,脏inode可以出现在bdi的好几个链表上。先是dirty链表(应该是文件系统放上去的),需要回写遍历时,先将dirty链表上的东西放到io链表上,再回写io链表上的东西。如果回写完了发现dirty链表上又有东西了,则把它们放到more_io链表上,但不处理它们,即认为回写已经完成。我也不知道有没有讲对,据说这样做是为了防活锁,找机会再看看吧。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值