|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
大家知道,在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,) U E% e, x% R4 C6 n
' _" T+ ?$ A: |- e" _
而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到磁盘上,在下面几种情况下,7 o. n, f+ z& p! D; s" A
系统会唤醒pdflush回写脏页:3 t* B% g& o" R6 f
1 、定时方式:( w; E( t5 @$ P3 R) x I( {# b
定时机制定时唤醒pdflush内核线程,周期为/proc/sys/vm/dirty_writeback_centisecs ,单位0 y! M7 h7 P5 d/ D; E
是(1/100)秒,每次周期性唤醒的pdflush线程并不是回写所有的脏页,而是只回写变脏时间超过0 O$ Y4 d8 J( f: z
/proc/sys/vm/dirty_expire_centisecs(单位也是1/100秒)。
2 W; i; Y" e6 e: {5 W/ p0 I注意:变脏的时间是以文件的inode节点变脏的时间为基准的,也就是说如果某个inode节点是10秒前变脏的,
, }9 s' J: t9 Xpdflush就认为这个inode对应的所有脏页的变脏时间都是10秒前,即使可能部分页面真正变脏的时间不到10秒,
8 ^- F; N6 F$ P& |8 x) W/ C$ S5 c$ ]& j细节可以查看内核函数wb_kupdate()。
* v+ T% s n& ]9 S( i5 n1 U0 ~8 y7 M& _- d* t/ u, A
2、 内存不足的时候:
; b* U8 o2 F+ H6 i; a2 l 这时并不将所有的dirty页写到磁盘,而是每次写大概1024个页面,直到空闲页面满足需求为止。
w4 D D( h" U. d7 V. j1 U9 P7 V/ m z" H( ^
3 、写操作时发现脏页超过一定比例:
. _5 `/ `: S0 s8 ] 当脏页占系统内存的比例超过/proc/sys/vm/dirty_background_ratio 的时候,write系统调用会唤醒
3 ?8 S, F/ d8 e1 J: ~. apdflush回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_background_ratio,但write系统调
4 ^: l" E, j S用不会被阻塞,立即返回。当脏页占系统内存的比例超过/proc/sys/vm/dirty_ratio的时候, write系
2 @4 e; L5 M( @1 i, M& i统调用会被被阻塞,主动回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_ratio,这一点在3 T! h# O W" M. w
2.4内核中是没有的。- Y- y& X2 \. M. f& {- S
# M: d* {: Y/ O& i# v4 、用户调用sync系统调用:( x y5 r; @- T9 p# c; A
这是系统会唤醒pdflush直到所有的脏页都已经写到磁盘为止。
" }! {. h4 {- q5 r# s3 F) d6 J1 d: B5 e2 }. x: _( w$ N; }
6 P1 r; A# x2 W& E9 u
一、简介 5 n8 n& a6 R; P: r7 Z
由于页高速缓存的缓存作用,写操作实际上会被延迟。
8 p0 V2 t- v, S$ c, p当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。3 p9 Y2 X5 K" T, o5 {5 H/ T% ^
在内存中累积起来的脏页最终必须被写回磁盘。
( _3 l" {0 V; Q1 @/ E g. h% ]& u7 D1 R5 X" `
在以下两种情况发生时,脏页被写回磁盘:
5 x3 @' ^1 L' l! H. 当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。 4 c5 ?( t; ]! P. x" F
. 当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,
6 C( P7 b2 t" W% R$ K/ Z8 n 以确保脏页不会无限期地驻留在内存中。; a, q3 z, x+ v) d5 g
! U0 ~ ]' t+ f6 J0 Q' \+ j上面两种工作的目的完全不同。4 F1 R8 E N) X: r9 t
实际上,在老内核中,这是由两个独立的内核线程分别完成的。. t0 L. q; U2 O6 \9 y
但是在2.6内核中,由一群内核线程—pdflush后台回写例程—统一执行两种工作。
$ Z8 x: x) x# E/ e j$ Q2 ~9 X6 v8 c/ f7 S& V
我们来看看这两个目标是如何具体实现的。0 |' ]* m+ O2 u/ y
首先,当系统中的空闲内存低于一个特定的阈值时,pdflush线程将脏页刷新回磁盘。3 R# g& v' n6 y5 o/ d- p
该后台回写例程的目的在于在可用物理内存过低时,释放脏页以重新获得内存。" |8 z6 G0 s% |) K5 G
特定的内存阈值可以通过dirty_background_ratio参数设置。
& e, R g. g; @9 T, c+ g当空闲内存比阈值dirty_ background_ratio还低时,内核便会调用函数wakeup_bdflush()唤醒一个pdflush线程,
: E& W, D" n9 L( J2 h1 s& w随后pdflush线程进一步调用函数background_writeout()开始将脏页写回磁盘。
}2 G* N1 y( E* ^2 S) W函数background_ writeout()需要一个长整型参数,该参数指定试图回写的页面数目。; l* u* E: k: E% q0 Z1 Y6 h3 W Q
3 W, N7 T# W9 a- x; n; Z函数background_writeout()会连续地写出数据,直到满足以下两个条件:! n* I+ y+ |. j
. 已经有指定的最小数目的页被写出到磁盘。
1 s0 |8 n" B$ d- c7 k. F" V. 空闲内存数已经回升,超过了阈值dirty_background_ratio。
, a! W4 O; q2 x% C$ ^- t2 o! h1 u! r2 f6 H: @) m
上述条件确保了pdflush操作可以减轻系统中内存不足的压力。
4 |. `, g2 ~; l% f* U回写操作不会在达到这两个条件前停止,除非pdflush写回了所有的脏页,没有剩下的脏页可再被写回了。$ r6 _! R7 n& Z" W; K f
1 c" h+ ~; L2 F, J/ a5 @
要满足第二个目标,pdflush后台例程会被周期性唤醒(和空闲内存是否过低无关),
& L8 n: _3 V- i! ]% K将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。
4 X) W) \, w+ ~加入系统发生崩溃,则内存会处于混乱之中,而那些在内存中还没来得及写回磁盘的脏页就会丢失,
1 H6 A3 H3 F [9 f# N1 L# x所以周期性同步回写非常重要。) O* }# }- E2 M: d: f" [$ \- b
% I! t; \ P, r: v6 j7 i在系统启动时,内核初始化一个定时器,让它周期地唤醒pdflush线程,随后使其运行函数wb_kupdate()。
& g+ o$ @5 L/ q6 n, I( ^) q4 h: F0 w该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。
9 N3 M8 S! `- k1 I8 U然后定时器将再次被初始化为百分之dirty_expire_ centisecs秒后唤醒pdflush线程。
# s4 O+ l& s3 \. a总而言之,pdflush线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。
7 @- [# S" Q0 w/ c S+ [% }: T& w. X* N, b
二、proc下的相关控制参数
$ F' Z8 E' |! `! m2 B3 P6 _+ G# q系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用设置它们。5 ]3 r7 Z. t0 a( `7 K% N( I8 t: ]
5 Q: w& L8 w+ g0 A; s% e, ~
1. /proc/sys/vm/dirty_ratio
, x e. L5 H/ B5 n这个参数控制一个进程在文件系统中的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,% y: W0 D4 p# V5 z/ j! L& |! j0 G
表示当一个进程中写缓冲使用到系统内存多少的时候,再有磁盘写操作时开始向磁盘写出数据。4 z- C+ K1 w0 l& n* ?& y
增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。7 b, E4 J* Q$ u, O! h' `7 ` h
但是,当你需要持续、恒定的写入场合时,应该降低其数值.9 u2 O% j: p, F9 ?3 s
一般缺省是 40。
1 W8 ^- `1 t$ I0 u+ M* s设置方法如下:
5 w5 Y: l j0 ~, N& H" cecho 30 >/proc/sys/vm/dirty_ratio
/ }4 x b1 }5 A' f7 d9 n1 q3 }2 [2 h3 O' a& x. {+ f
2. /proc/sys/vm/dirty_background_ratio
5 J f1 o. b1 r. h这个参数控制文件系统的pdflush进程,在何时刷新磁盘。单位是百分比,表示系统总内存的百分比,
* ~% V x4 B" n3 M# F! Z意思是当磁盘的脏数据缓冲到系统内存多少的时候,pdflush开始把脏数据刷新到磁盘。* R1 T# k* r; M
增大会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。" |( A! F8 r* d' F3 o! H
但是,当你需要持续、恒定的写入场合时,应该降低其数值.
H1 f% [) i' A- c' C4 K ]一般缺省是10。
3 ?0 c# \5 t- u设置方法如下:
8 [% i% D, A3 Decho 8 >/proc/sys/vm/dirty_background_ratio
" w) f7 p. K0 Y. n+ u
$ @. R) ~5 P' Y) B& T; t0 ^% `3. /proc/sys/vm/dirty_writeback_centisecs; y' c; S4 p8 w* x1 B7 f1 {! ?
Pdflush写后台进程每隔多久被唤醒并执行把脏数据写出到硬盘。单位是 1/100 秒。
, Z9 a6 R4 H( X如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。
9 v1 |3 \' X- e8 U% |1 v7 Z% M; U; m, I缺省数值是500,也就是 5 秒。
* \1 p v, d6 W$ u设置方法如下:" s& E6 X( z5 X" t$ @- k
# echo 200 >/proc/sys/vm/dirty_writeback_centisecs. s2 c; d; Y" A6 K7 n
# e/ t% s! [1 L5 ]
4. /proc/sys/vm/dirty_expire_centisecs
" m+ i3 o2 m; X这个参数声明Linux内核写缓冲区里面的脏数据多“旧”了之后,pdflush 进程就开始考虑写到磁盘中去。
7 P& _& Z, ` A1 u9 [& Z单位是 1/100秒。
! \9 c+ w& q! d6 L对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。
# G+ W( r3 A2 S0 X/ Y _0 |9 w# l( m缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新磁盘。3 ~+ `( v& H( w5 w% r
建议设置为 1500,也就是15秒算旧。
# w- X# u( ^5 u, w1 ]设置方法如下:
. e4 e1 R8 U+ I* g* y6 D/ {+ B: Gecho 1500 >/proc/sys/vm/dirty_expire_centisecs3 d) T; c/ D$ Q, m2 T( H( { `
0 }& w3 O* |% o, _- z
三、内核参数修改后的生效
" ? {2 f- O% G+ _: ] HLinux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统," R$ o" l$ g" D' { t5 B0 b
这个功能是通过/proc虚拟文件系统实现的。
- I% @: B6 e6 C$ _& R
& `: W+ z1 }& k; A) G在/proc/sys目录下存放着大多数的内核参数,并且设计成可以在系统运行的同时进行更改,
! T: H% Z2 |$ j3 X n可以通过更改/proc/sys中内核参数对应的文件达到修改内核参数的目的(修改过后,保存配置文件就马上自动生效),
. `0 x G% Z/ I" `$ U/ W不过重新启动机器后之前修改的参数值会失效,所以只能是一种临时参数变更方案。
* ^9 _0 ?$ ~" q- m- i8 v5 q(适合调试内核参数优化值的时候使用,如果设置值有问题,重启服务器还原原来的设置参数值了。简单方便。); `/ x5 b7 t: r
# R- M' F: j2 h. @3 S但是如果调试内核参数优化值结束后,需要永久保存参数值,, O% | I- g, ^: w/ k, U
就要通过修改/etc/sysctl.conf内的内核参数来永久保存更改。
' F) R4 L0 K7 y0 ^5 ]1 l$ o; u, V" T但只是修改sysctl文件内的参数值,确认保存修改文件后,设定的参数值并不会马上生效,4 f, H/ ?- u# ^% g, e8 o! V. @7 Z' E
如果想使参数值修改马上生效,并且不重启服务器,可以执行下面的命令:& a+ R3 g6 H8 k# `; A# G6 p, h
# sysctl –p( P! t6 B* n* y# Q/ V9 J3 B m9 Q
8 v" e ~8 P3 t下面介绍一下/proc/sys下内核文件与配置文件sysctl.conf中变量的对应关系:! J. Q: s/ e ]
由于可以修改的内核参数都在/proc/sys目录下,所以sysctl.conf的变量名省略了目录的前面部分(/proc/sys)。
3 G+ ^6 Z3 K% t; R! F即将/proc/sys中的文件转换成sysctl中的变量依据下面两个简单的规则:
$ s1 Z# F g7 [1.去掉前面部分/proc/sys6 [) d4 A5 T- W+ H6 X) B6 l# n
2.将文件名中的斜杠变为点' D- S; ?. u9 B% w4 `# H ~
" M: Y. k5 |6 H6 k/ R这两条规则可以将/proc/sys中的任一文件名转换成sysctl中的变量名。
! i8 ~5 o# ?. b& [6 k" H例如:9 V: o1 K: H7 g
/proc/sys/net/ipv4/ip_forward =》 net.ipv4.ip_forward, k. Y8 B& e$ F- ~ h7 o
/proc/sys/kernel/hostname =》 kernel.hostname5 i* X; A E1 I1 l- h; D0 F; b1 }
1 C6 S9 d& u3 G0 k* z2 ?0 N! J4 K/ P' q
可以使用下面命令查询所有可修改的变量名
+ |) ^- v1 R* |3 D # sysctl –a
0 d) f, d8 }/ A* C. E. f3 c% E' t7 B8 C6 z7 t( [7 O9 n
k% b) [' S; ~& Z1 ~ |
|