|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
大家知道,在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,
$ o/ R0 A9 P& J! x% g1 O! _- G2 C( X3 c
而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到磁盘上,在下面几种情况下,
! O. w/ H4 U; j3 |系统会唤醒pdflush回写脏页:
( Q* s' G2 l0 w' \9 k1 、定时方式:
7 s3 F% n; q' q: M% K6 ?! M 定时机制定时唤醒pdflush内核线程,周期为/proc/sys/vm/dirty_writeback_centisecs ,单位
. s: w- A' r8 i. v5 Q7 }5 G7 a是(1/100)秒,每次周期性唤醒的pdflush线程并不是回写所有的脏页,而是只回写变脏时间超过
9 f$ A& {0 z; z3 L/proc/sys/vm/dirty_expire_centisecs(单位也是1/100秒)。! e$ u% ^" ?* } {6 i7 Q5 \; A
注意:变脏的时间是以文件的inode节点变脏的时间为基准的,也就是说如果某个inode节点是10秒前变脏的,
6 e, v. r$ b( r/ P3 Dpdflush就认为这个inode对应的所有脏页的变脏时间都是10秒前,即使可能部分页面真正变脏的时间不到10秒,9 \! M% `9 ^+ q
细节可以查看内核函数wb_kupdate()。! g+ Z# t- W$ L
# \8 O `! V2 E
2、 内存不足的时候:
/ W. g/ s3 L( m 这时并不将所有的dirty页写到磁盘,而是每次写大概1024个页面,直到空闲页面满足需求为止。& x$ ~- m6 p4 O# W/ \: ~ i
% N4 h# O0 J5 x/ C2 p0 E3 、写操作时发现脏页超过一定比例:6 _1 p7 F6 D% {; U2 e
当脏页占系统内存的比例超过/proc/sys/vm/dirty_background_ratio 的时候,write系统调用会唤醒
O6 |! c: o7 Xpdflush回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_background_ratio,但write系统调
5 Z: h1 c2 l1 X- x. k2 B! \# E: n用不会被阻塞,立即返回。当脏页占系统内存的比例超过/proc/sys/vm/dirty_ratio的时候, write系
9 n% H/ a1 q |4 f' J. k2 u统调用会被被阻塞,主动回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_ratio,这一点在
; D, }, T! i) `% T, s ^" {) E2.4内核中是没有的。
+ ]. n! a4 {. r% r' B/ u, a. }. i- q- L: R5 `# }$ a9 j8 k
4 、用户调用sync系统调用:! j! H- p: u0 H
这是系统会唤醒pdflush直到所有的脏页都已经写到磁盘为止。
0 X2 F$ r; j1 r5 _1 q F
0 u" t& I. L" s8 f
- x+ A' X9 |! C, `6 a一、简介
$ t' f3 u) M* [! { V由于页高速缓存的缓存作用,写操作实际上会被延迟。' |( @9 @" M- } S( F
当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。0 P; j: d. w7 Q5 @+ _, I9 l
在内存中累积起来的脏页最终必须被写回磁盘。
8 u) x4 r- Z9 Z) m3 D, A0 Z2 y& |( H/ h5 F
在以下两种情况发生时,脏页被写回磁盘:
/ `, l( G' H" o3 q2 F' e4 }. 当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。 G2 F8 m# O- z, i- `
. 当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,
2 Q! ?0 R2 V7 K6 c 以确保脏页不会无限期地驻留在内存中。
/ T0 ] U- G; I
8 Z/ u! \. S: f' y& c2 R. {上面两种工作的目的完全不同。1 J& {# _( b; A" [& g. R
实际上,在老内核中,这是由两个独立的内核线程分别完成的。
+ l" }, R* k( C, Z, ~& Q但是在2.6内核中,由一群内核线程—pdflush后台回写例程—统一执行两种工作。. y6 R2 G/ B ] {
7 Y/ `1 x4 |( Y" K0 g3 j1 q我们来看看这两个目标是如何具体实现的。
2 H& f( p7 `. v$ ]5 X7 F6 T首先,当系统中的空闲内存低于一个特定的阈值时,pdflush线程将脏页刷新回磁盘。
" x: \ _/ X9 U. O" A5 }9 i该后台回写例程的目的在于在可用物理内存过低时,释放脏页以重新获得内存。4 G2 p; m8 [& |. V
特定的内存阈值可以通过dirty_background_ratio参数设置。0 G9 T) d9 Y' x7 O" A' i
当空闲内存比阈值dirty_ background_ratio还低时,内核便会调用函数wakeup_bdflush()唤醒一个pdflush线程,8 g* X/ X: s) c; v3 S0 f
随后pdflush线程进一步调用函数background_writeout()开始将脏页写回磁盘。
/ Q% g, g% w/ B- |' V* X函数background_ writeout()需要一个长整型参数,该参数指定试图回写的页面数目。
3 T; B6 u. s/ A4 _
# K" ~) p! \( Q函数background_writeout()会连续地写出数据,直到满足以下两个条件:
8 O) r7 Z7 {. p$ T) |. 已经有指定的最小数目的页被写出到磁盘。
. p' N# v. U; A: \* [, }. 空闲内存数已经回升,超过了阈值dirty_background_ratio。* Z! L1 s7 Y h# n4 U/ X4 ?. @* U
& h4 ]7 J! w3 g上述条件确保了pdflush操作可以减轻系统中内存不足的压力。# C+ b$ I+ ~, _. H
回写操作不会在达到这两个条件前停止,除非pdflush写回了所有的脏页,没有剩下的脏页可再被写回了。, M0 u+ s' ?/ A5 u; O- k
+ ^& S, ?1 S- B0 n, @; z
要满足第二个目标,pdflush后台例程会被周期性唤醒(和空闲内存是否过低无关),
0 u. p, b5 w. I8 x% Z将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。$ p' q, P* [& o$ M& `: Y/ \5 `% {
加入系统发生崩溃,则内存会处于混乱之中,而那些在内存中还没来得及写回磁盘的脏页就会丢失,6 a9 G* H& B h5 ?
所以周期性同步回写非常重要。& a' d# Z% e8 ]1 @4 ?
% U3 x: m! P4 P3 q在系统启动时,内核初始化一个定时器,让它周期地唤醒pdflush线程,随后使其运行函数wb_kupdate()。
p( l# C' ]) r' p8 u" X该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。1 h. H7 a5 w; G. H! v: w( C& z& }
然后定时器将再次被初始化为百分之dirty_expire_ centisecs秒后唤醒pdflush线程。- e3 ~/ ?; [' S9 [! j( R. F# R
总而言之,pdflush线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。 7 O A9 k8 q6 `8 G& v
/ B! ?/ E3 a, X4 \* A- d
二、proc下的相关控制参数
8 _1 j& O# s- w# i系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用设置它们。4 r0 Y8 J) x2 [! V _" @) i, B
1 u3 g8 b: |: U# f6 [& b& }2 x1 f! b D1. /proc/sys/vm/dirty_ratio" h0 v Y0 Y4 n, K
这个参数控制一个进程在文件系统中的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,
( J$ S% D. J% u2 y6 A表示当一个进程中写缓冲使用到系统内存多少的时候,再有磁盘写操作时开始向磁盘写出数据。
- O' |& Y! D# Y* h6 f0 R @1 j增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
4 }4 Y4 l/ R+ L" I* |9 b, p但是,当你需要持续、恒定的写入场合时,应该降低其数值.
% }$ R5 t0 Z, S, ]! d: q一般缺省是 40。
2 D6 C( O- x( o1 c/ G7 A" B设置方法如下:
6 f) H# t! r! @* @echo 30 >/proc/sys/vm/dirty_ratio
s9 l/ ]7 w( v( [" L7 D% A) S4 \9 Q+ d( I* h) @
2. /proc/sys/vm/dirty_background_ratio
4 N& X: j+ g6 w# z9 @4 b这个参数控制文件系统的pdflush进程,在何时刷新磁盘。单位是百分比,表示系统总内存的百分比,
1 T( @% z% A$ s- q# T, Z意思是当磁盘的脏数据缓冲到系统内存多少的时候,pdflush开始把脏数据刷新到磁盘。- E1 J4 A' ^& D& Y* o' ]( ?: s
增大会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
/ D3 [) b) \) x8 T m但是,当你需要持续、恒定的写入场合时,应该降低其数值.7 {8 f( F- ?9 q1 ]! n
一般缺省是10。$ _" l+ v; J6 J! T0 }( {! ?
设置方法如下:
' e' e9 y6 `: u Yecho 8 >/proc/sys/vm/dirty_background_ratio
2 w" p7 |# P( p' m# x1 r
8 l5 l% t1 Y$ {, ~% L3. /proc/sys/vm/dirty_writeback_centisecs' a* O) ]3 r5 @+ r9 E" C) M6 r' I
Pdflush写后台进程每隔多久被唤醒并执行把脏数据写出到硬盘。单位是 1/100 秒。
) B, n. ~5 ^/ I& ]4 k1 K如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。
( z' t# X+ J6 y0 N' W缺省数值是500,也就是 5 秒。9 q/ u! Y! L! t4 _! T& I
设置方法如下:
! \0 b1 t: p! S# echo 200 >/proc/sys/vm/dirty_writeback_centisecs
7 ^, E- q# z! a6 C+ ~
5 I ^' x& R9 K& {6 n( N( c6 r4. /proc/sys/vm/dirty_expire_centisecs, N B1 {' y& ^1 D
这个参数声明Linux内核写缓冲区里面的脏数据多“旧”了之后,pdflush 进程就开始考虑写到磁盘中去。3 j/ ], }0 [* {
单位是 1/100秒。& \) }8 ~- B4 |9 d0 D% k9 m$ [
对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。; a( f& c5 ^6 y
缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新磁盘。
' P& V+ ~; I; Q建议设置为 1500,也就是15秒算旧。( M& y8 \8 i9 x9 `) o" `1 K
设置方法如下:; ?% Z: h8 ~7 j# h% U; g. x1 T
echo 1500 >/proc/sys/vm/dirty_expire_centisecs$ z3 ^( d1 r! @1 `
: F) {4 L. E; U. s4 O/ v9 g三、内核参数修改后的生效# Y; F% I2 E6 O; i8 l& }
Linux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统,
2 |5 x7 ?& A0 N# ]这个功能是通过/proc虚拟文件系统实现的。. Y, G$ d, ~( g6 p: f0 g
3 p( B( i2 W/ w9 c
在/proc/sys目录下存放着大多数的内核参数,并且设计成可以在系统运行的同时进行更改,
+ X% _) Y$ n2 s- k* ^可以通过更改/proc/sys中内核参数对应的文件达到修改内核参数的目的(修改过后,保存配置文件就马上自动生效),
) _' I# Y1 f0 D5 H$ l5 d6 g$ v2 B不过重新启动机器后之前修改的参数值会失效,所以只能是一种临时参数变更方案。
& @4 w" Z/ ~: [; b0 M(适合调试内核参数优化值的时候使用,如果设置值有问题,重启服务器还原原来的设置参数值了。简单方便。)
6 ]/ I* ]5 E* Z: L+ J* |" `( s" k1 } O8 k
但是如果调试内核参数优化值结束后,需要永久保存参数值,% ~5 t& j# m1 {9 L
就要通过修改/etc/sysctl.conf内的内核参数来永久保存更改。
6 m( L2 n3 E% |/ h4 r- {* i但只是修改sysctl文件内的参数值,确认保存修改文件后,设定的参数值并不会马上生效,
4 i a9 ~# p0 S _ N如果想使参数值修改马上生效,并且不重启服务器,可以执行下面的命令:
3 ]) Z# H0 L: r3 s: v # sysctl –p
- I5 f6 F3 O+ F* C
, r) m. [1 U1 ]" F下面介绍一下/proc/sys下内核文件与配置文件sysctl.conf中变量的对应关系:
) f8 f) I5 J: x5 V; R1 w: P由于可以修改的内核参数都在/proc/sys目录下,所以sysctl.conf的变量名省略了目录的前面部分(/proc/sys)。
4 f+ G B6 D1 [即将/proc/sys中的文件转换成sysctl中的变量依据下面两个简单的规则:
0 |) |0 b, T4 Q' T/ e$ d4 @. R1.去掉前面部分/proc/sys
/ M& c- {4 ] O0 `! y3 k. W3 o2.将文件名中的斜杠变为点
+ }( F3 l4 N1 |
, G, i0 r; I7 @- F. P' Q8 i" e这两条规则可以将/proc/sys中的任一文件名转换成sysctl中的变量名。' o. a8 ^) V1 _" f0 ]
例如:
) a5 {& N s2 w- ?/proc/sys/net/ipv4/ip_forward =》 net.ipv4.ip_forward. y& e$ h" n! F2 w
/proc/sys/kernel/hostname =》 kernel.hostname
: B* r1 R& b+ w2 S
& k4 D( ^% j1 r! \9 m% ]$ z可以使用下面命令查询所有可修改的变量名
* q! t2 G* ~$ C X) J9 [9 h # sysctl –a
& \5 d5 t. X1 m2 r% l# T' _) r6 f8 F9 `! h, y! b9 D) F c9 T
' `6 k2 u0 }0 P9 p- v: Q& K- K2 u
|
|