ratelimite_pages、write_trunk的计算
对于ratelimit_pages,代码中的注释为 "After a CPU has dirtied this many pages, balance_dirty_pages_ratelimited will look to see if it needs to force writeback or throttling"。
即:当一个cpu弄脏了这么多页后,balance_dirty_pages()函数将会检查是否需要回写。而要求的回写量write_trunk,则由函数sync_writeback_page()计算得出,其全部代码为:
static inline long sync_writeback_pages(void)
{
return ratelimit_pages + ratelimit_pages / 2;
}
即,write_trunk = 1.5 * ratelimit_pages,1.5倍的原因是:"It should be somewhat larger than RATELIMIT_PAGES to ensure that reasonably large amounts of I/O are submitted",即回写量应该比ratelimit_pages大,确保合理数目的I/O被提交。
ratelimit_pages初始化为32页,但系统在启动过程中会通过调用函数set_ratelimit()来根据系统环境重新设定(start_kernel()-->page_writeback_init()-->set_ratelimit())。
set_ratelimit()函数的代码很少,全部代码如下所示:
ratelimit_pages = total_pages / (num_online_cpus() * 32);
if (ratelimit_pages < 16)
ratelimit_pages = 16;
if (ratelimit_pages * PAGE_CACHE_SIZE > 4096 * 1024)
ratelimit_pages = (4096 * 1024) / PAGE_CACHE_SIZE;
其中total_pages为"The total number of pages in the machine",由此可知ratelimit_pages是系统中页总数的3%在每个cpu上的分量,且不小于16页,不大于1024页。
设定一个这样的量的目的是:"Here we set ratelimit_pages to a level which ensures that when all CPUs are dirtying in parallel, we cannot go more than 3% (1/32) over the dirty memory thresholds before writeback cuts in.",即:当多个cpu并行的使页变脏时,确保超出脏页阈值的脏页不会达到系统页数的3%。
一开始,我看到注释,怎么都想不通,"we cannot go more than 3% (1/32) over the dirty memory thresholds before writeback cuts in"是什么意思,"over the dirty memory thresholds"体现在什么地方。结合balance_dirty_pages()函数的流程,我想我终于明白了,为什么说“超出脏页阈值的脏页不会达到系统页数的3%”,并且对balance_dirty_pages_ratelimited()函数有了新的理解。
balance_dirty_pages()函数在调用write_inodes()之前会检测系统中的脏页是否超过了脏阈值。只有在超过脏页阈值的情况下,才会调用write_inodes()回写数量为1.5*ratelimit_pages的一些页,而ratelimit_pages正是系统中总页数的3%在每个cpu上的分量。
但是,在超出了脏阈值后,回写1.5*ratelimit_pages个页,并不能保证“超出脏页阈值的脏页不会达到系统页数的3%”。
那么怎样才能保证这一点呢?最简单的办法就是每写脏一页就检查是否超过了脏阈值,如果超过了就回写。但是每写一页就检查势必会降低系统性能,于是系统设定了一个“频率限制”,用以限制balance_dirty_pages()函数的调用,即"so try to avoid calling it too often (ratelimiting)",而这个“ratelimiting”又是通过ratelimit_pages来实现的。
balance_dirty_pages_ratelimited_nr()函数每次调用时,对一个per_cpu变量ratelimit进行加一操作,当这个ratelimit达到ratelimit_pages后,就将其清0,并调用balance_dirty_pages()函数,balance_dirty_pages()函数将检查脏页数是否超过了脏阈值,然后再进行进一步处理。即:每次写脏系统所有页3%在cpu上的分量,就检查一次脏页是否超过了脏阈值,这样就可以确保“we cannot go more than 3% (1/32) over the dirty memory thresholds”了。
转自:
http://blog.csdn.net/yangp01/article/details/5483225