一、简介
由于页高速缓存的缓存作用,写操作实际上会被延迟。
当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。
在内存中累积起来的脏页最终必须被写回磁盘。
在以下两种情况发生时,脏页被写回磁盘:
. 当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。
. 当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,
以确保脏页不会无限期地驻留在内存中。
上面两种工作的目的完全不同。
实际上,在老内核中,这是由两个独立的内核线程分别完成的。
但是在2.6内核中,由一群内核线程—pdflush后台回写例程—统一执行两种工作。
我们来看看这两个目标是如何具体实现的。
首先,当系统中的空闲内存低于一个特定的阈值时,pdflush线程将脏页刷新回磁盘。
该后台回写例程的目的在于在可用物理内存过低时,释放脏页以重新获得内存。
特定的内存阈值可以通过dirty_background_ratio参数设置。
当空闲内存比阈值dirty_ background_ratio还低时,内核便会调用函数wakeup_bdflush()唤醒一个pdflush线程,
随后pdflush线程进一步调用函数background_writeout()开始将脏页写回磁盘。
函数background_ writeout()需要一个长整型参数,该参数指定试图回写的页面数目。
函数background_writeout()会连续地写出数据,直到满足以下两个条件:
. 已经有指定的最小数目的页被写出到磁盘。
. 空闲内存数已经回升,超过了阈值dirty_background_ratio。
上述条件确保了pdflush操作可以减轻系统中内存不足的压力。
回写操作不会在达到这两个条件前停止,除非pdflush写回了所有的脏页,没有剩下的脏页可再被写回了。
要满足第二个目标,pdflush后台例程会被周期性唤醒(和空闲内存是否过低无关),
将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。
加入系统发生崩溃,则内存会处于混乱之中,而那些在内存中还没来得及写回磁盘的脏页就会丢失,
所以周期性同步回写非常重要。
在系统启动时,内核初始化一个定时器,让它周期地唤醒pdflush线程,随后使其运行函数wb_kupdate()。
该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。
然后定时器将再次被初始化为百分之dirty_expire_ centisecs秒后唤醒pdflush线程。
总而言之,pdflush线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。
二、proc下的相关控制参数
系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用设置它们。
1. /proc/sys/vm/dirty_ratio
这个参数控制一个进程在文件系统中的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,
表示当一个进程中写缓冲使用到系统内存多少的时候,再有磁盘写操作时开始向磁盘写出数据。
增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
但是,当你需要持续、恒定的写入场合时,应该降低其数值.
一般缺省是 40。
设置方法如下:
echo 30 >/proc/sys/vm/dirty_ratio
2. /proc/sys/vm/dirty_background_ratio
这个参数控制文件系统的pdflush进程,在何时刷新磁盘。单位是百分比,表示系统总内存的百分比,
意思是当磁盘的脏数据缓冲到系统内存多少的时候,pdflush开始把脏数据刷新到磁盘。
增大会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
但是,当你需要持续、恒定的写入场合时,应该降低其数值.
一般缺省是10。
设置方法如下:
echo 8 >/proc/sys/vm/dirty_background_ratio
3. /proc/sys/vm/dirty_writeback_centisecs
Pdflush写后台进程每隔多久被唤醒并执行把脏数据写出到硬盘。单位是 1/100 秒。
如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。
缺省数值是500,也就是 5 秒。
设置方法如下:
# echo 200 >/proc/sys/vm/dirty_writeback_centisecs
4. /proc/sys/vm/dirty_expire_centisecs
这个参数声明Linux内核写缓冲区里面的脏数据多“旧”了之后,pdflush 进程就开始考虑写到磁盘中去。
单位是 1/100秒。
对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。
缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新磁盘。
建议设置为 1500,也就是15秒算旧。
设置方法如下:
echo 1500 >/proc/sys/vm/dirty_expire_centisecs
三、内核参数修改后的生效
Linux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统,
这个功能是通过/proc虚拟文件系统实现的。
在/proc/sys目录下存放着大多数的内核参数,并且设计成可以在系统运行的同时进行更改,
可以通过更改/proc/sys中内核参数对应的文件达到修改内核参数的目的(修改过后,保存配置文件就马上自动生效),
不过重新启动机器后之前修改的参数值会失效,所以只能是一种临时参数变更方案。
(适合调试内核参数优化值的时候使用,如果设置值有问题,重启服务器还原原来的设置参数值了。简单方便。)
但是如果调试内核参数优化值结束后,需要永久保存参数值,
就要通过修改/etc/sysctl.conf内的内核参数来永久保存更改。
但只是修改sysctl文件内的参数值,确认保存修改文件后,设定的参数值并不会马上生效,
如果想使参数值修改马上生效,并且不重启服务器,可以执行下面的命令:
# sysctl –p
下面介绍一下/proc/sys下内核文件与配置文件sysctl.conf中变量的对应关系:
由于可以修改的内核参数都在/proc/sys目录下,所以sysctl.conf的变量名省略了目录的前面部分(/proc/sys)。
即将/proc/sys中的文件转换成sysctl中的变量依据下面两个简单的规则:
1.去掉前面部分/proc/sys
2.将文件名中的斜杠变为点
这两条规则可以将/proc/sys中的任一文件名转换成sysctl中的变量名。
例如:
/proc/sys/net/ipv4/ip_forward =》 net.ipv4.ip_forward
/proc/sys/kernel/hostname =》 kernel.hostname
可以使用下面命令查询所有可修改的变量名
# sysctl –a
阅读(4580) | 评论(0) | 转发(1) |