- 论坛徽章:
- 0
|
众所周知linux对块设备脏页设置有如下两个参数:
1. /proc/sys/vm/dirty_background_ratio
2. /proc/sys/vm/dirty_ratio
对2.6.29内核,对以上两个参数的实现原理,我做了如下的分析。
在对块设备写入数据时,会调用balance_dirty_pages_ratelimited()判断是否需要脏页回收。
balance_dirty_pages_ratelimited() -> balance_dirty_pages_ratelimited_nr -> balance_dirty_pages();
最后实现脏页处理的函数在banalce_dirty_pages中。分析此函数发现,dirty_background_ratio 很好理解,就是内存中的脏页大于设置的这个比例,就启动后台pdflush刷写数据。
if ((laptop_mode && pages_written) ||
(!laptop_mode && (global_page_state(NR_FILE_DIRTY)
+ global_page_state(NR_UNSTABLE_NFS)
> background_thresh)))
pdflush_operation(background_writeout, 0);
但是dirty_ratio参数的作用看起来稍微复杂一些,get_dirty_limits()中会做如下计算:
dirty = (dirty_ratio * available_memory) / 100;
/*
* Calculate this BDI's share of the dirty ratio.
*/
bdi_writeout_fraction(bdi, &numerator, &denominator);
bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100;
bdi_dirty *= numerator;
do_div(bdi_dirty, denominator);
以上计算,会根据bdi_writeout_fraction计算一个分数,dirty乘以这个分数算出,这个bdi可以占用内存的比例。
static void bdi_writeout_fraction(struct backing_dev_info *bdi,
long *numerator, long *denominator)
{
if (bdi_cap_writeback_dirty(bdi)) {
prop_fraction_percpu(&vm_completions, &bdi->completions,
numerator, denominator);
} else {
*numerator = 0;
*denominator = 1;
}
}
/*
* Obtain a fraction of this proportion
*
* p_{j} = x_{j} / (period/2 + t % period/2)
*/
void prop_fraction_percpu(struct prop_descriptor *pd,
struct prop_local_percpu *pl,
long *numerator, long *denominator)
{
struct prop_global *pg = prop_get_global(pd);
unsigned long period_2 = 1UL << (pg->shift - 1);
unsigned long counter_mask = period_2 - 1;
unsigned long global_count;
prop_norm_percpu(pg, pl);
*numerator = percpu_counter_read_positive(&pl->events);
global_count = percpu_counter_read(&pg->events);
*denominator = period_2 + (global_count & counter_mask);
prop_put_global(pd, pg);
}
现在的问题是,这个分数的分子分母是怎么计算的,为什么这么计算,有什么好处,基于什么考虑的?
我分析的代码,觉得这么计算的原理是根据这个设备一段时间的流量,与系统总io流量的比例进行计算。
此处代码的思想是流量大的设备可以多占用系统缓存资源。流量小的设备,不允许占用太多缓存资源。防止资源浪费。
不知道我的理解是否正确,请大家拍砖。
|
|