EDA365电子论坛网

标题: pdflush进程详解 [打印本页]

作者: pulbieup    时间: 2020-4-17 10:08
标题: pdflush进程详解
大家知道,在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,) T& t( r# I5 Q. N0 v9 ^

8 D6 k/ L' V8 M( T而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到磁盘上,在下面几种情况下,. \0 l( I; y" s$ W
系统会唤醒pdflush回写脏页:
( }& d" V; K8 x$ Y* }1 、定时方式:
$ q- A& a' J6 C! _     定时机制定时唤醒pdflush内核线程,周期为/proc/sys/vm/dirty_writeback_centisecs ,单位
) d" q8 s+ _6 T1 E: w! f! S是(1/100)秒,每次周期性唤醒的pdflush线程并不是回写所有的脏页,而是只回写变脏时间超过! d5 p+ k8 n( [) H
/proc/sys/vm/dirty_expire_centisecs(单位也是1/100秒)。
9 F& U- R* \& _8 l' r注意:变脏的时间是以文件的inode节点变脏的时间为基准的,也就是说如果某个inode节点是10秒前变脏的,
! U, S1 R; ?- Epdflush就认为这个inode对应的所有脏页的变脏时间都是10秒前,即使可能部分页面真正变脏的时间不到10秒,
: j- [6 r  A/ C+ M细节可以查看内核函数wb_kupdate()。
: r# b! D2 K  S  p& d( U7 p$ h) A' I+ f3 |3 _7 j
2、 内存不足的时候:: y5 }2 O3 J6 K
    这时并不将所有的dirty页写到磁盘,而是每次写大概1024个页面,直到空闲页面满足需求为止。
; W7 l3 T1 @: y" A! W. [5 y" s$ j9 M! I( \
3 、写操作时发现脏页超过一定比例:
" s+ {6 M8 C$ Z3 L* V& z- H* G' P, r    当脏页占系统内存的比例超过/proc/sys/vm/dirty_background_ratio 的时候,write系统调用会唤醒
) R0 o2 ]3 j" y. p) a6 L! Fpdflush回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_background_ratio,但write系统调) w! h$ Y1 V# [' D2 b
用不会被阻塞,立即返回。当脏页占系统内存的比例超过/proc/sys/vm/dirty_ratio的时候, write系. u: R, f4 e5 Y  J' l
统调用会被被阻塞,主动回写dirty page,直到脏页比例低于/proc/sys/vm/dirty_ratio,这一点在
; O( x3 k9 _: `$ p* L* G: y2.4内核中是没有的。
% i3 p+ e: q% y& V6 H  t4 Z2 y
+ x7 R0 M( m4 Z8 F6 D. l4 、用户调用sync系统调用:/ x; Y" _$ j$ d: U- g. y
    这是系统会唤醒pdflush直到所有的脏页都已经写到磁盘为止。
" |- v% l7 K5 b' @$ _6 b# T. d) Z8 b
0 l! g- _% K5 B+ d$ {: \  o
一、简介
! ]2 q% {9 r! q: \% k% H, a9 J由于页高速缓存的缓存作用,写操作实际上会被延迟。
& K  D# z, s8 @& [; d当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。; \8 d# C4 T7 ^1 B! L
在内存中累积起来的脏页最终必须被写回磁盘。0 |; g; N% a8 m. _
7 J% G* U7 ?2 k3 i7 Q$ |
在以下两种情况发生时,脏页被写回磁盘:
' K. u! m& t2 }) E.  当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。 . i0 U/ l* _+ s* P$ d/ P
.  当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,
) Y! }( B& p" w  F# B5 L   以确保脏页不会无限期地驻留在内存中。* k4 }; G1 A9 i" D' @& N5 \
) Z; r7 s0 J5 O' V" C6 M
上面两种工作的目的完全不同。7 c" X4 ?$ r3 D' i, f: e) P8 F
实际上,在老内核中,这是由两个独立的内核线程分别完成的。- M* g5 `2 K! V- Q+ s
但是在2.6内核中,由一群内核线程—pdflush后台回写例程—统一执行两种工作。% B3 i! ]8 O& L' G3 N1 P

4 L: U: }, A* D( |我们来看看这两个目标是如何具体实现的。# ~7 g5 V2 _+ j: F& E
首先,当系统中的空闲内存低于一个特定的阈值时,pdflush线程将脏页刷新回磁盘。
6 K1 d8 _) p# b& k该后台回写例程的目的在于在可用物理内存过低时,释放脏页以重新获得内存。
! R% G/ S! S, _. W( A$ f特定的内存阈值可以通过dirty_background_ratio参数设置。( t9 {5 B, ^; x5 W4 d/ ~' U
当空闲内存比阈值dirty_ background_ratio还低时,内核便会调用函数wakeup_bdflush()唤醒一个pdflush线程,
  D- y, x; P% Q2 ~; b" f0 j$ Y随后pdflush线程进一步调用函数background_writeout()开始将脏页写回磁盘。9 h( j6 ^2 q' x9 e9 S* b
函数background_ writeout()需要一个长整型参数,该参数指定试图回写的页面数目。
) e1 |, v6 @- Y3 [% a% {
, y4 J" @) c9 O* d函数background_writeout()会连续地写出数据,直到满足以下两个条件:& V0 H3 G, c& c6 c, Z. Y0 }& p2 R5 S
.  已经有指定的最小数目的页被写出到磁盘。 4 [) E0 H4 ^& v7 k+ ?' G9 z
.  空闲内存数已经回升,超过了阈值dirty_background_ratio。: ?+ V: ^7 H( j' q
9 u, Z1 P- B' J) ?
上述条件确保了pdflush操作可以减轻系统中内存不足的压力。
* E: h- b5 ]& x2 b$ K- T, \5 G回写操作不会在达到这两个条件前停止,除非pdflush写回了所有的脏页,没有剩下的脏页可再被写回了。& E8 ~8 J1 X6 R( a) Q1 S# |

) n( B* v5 c9 B2 n0 G" p+ g要满足第二个目标,pdflush后台例程会被周期性唤醒(和空闲内存是否过低无关),1 C/ X9 p6 j8 t
将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。) _0 h: P: ]4 N  J4 s! |- `
加入系统发生崩溃,则内存会处于混乱之中,而那些在内存中还没来得及写回磁盘的脏页就会丢失,: y( G  {/ X; v
所以周期性同步回写非常重要。- x0 b, U2 }  R; U% a0 F

% q  q, {% ?* ]- m8 P在系统启动时,内核初始化一个定时器,让它周期地唤醒pdflush线程,随后使其运行函数wb_kupdate()。4 G% U7 m0 B$ B' k& `
该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。  }8 w9 T' m9 Q& y7 O! \
然后定时器将再次被初始化为百分之dirty_expire_ centisecs秒后唤醒pdflush线程。  ?% q0 |( v4 o" u8 O/ M$ K" b
总而言之,pdflush线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。
" M( n0 V, |$ j- r/ Y; m. o7 w1 b! E( y( u' r6 t; n
二、proc下的相关控制参数
* k: L, \) _: b* {$ l7 A* l, e( c系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用设置它们。
  {7 B, }$ Z% p: f2 d- r- l6 Y& B- p9 P8 p9 @6 ]% [
1. /proc/sys/vm/dirty_ratio9 ^" p7 z7 A6 J6 {/ b
这个参数控制一个进程在文件系统中的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比," d4 M" o- C, u$ B& y) \- p& T$ O
表示当一个进程中写缓冲使用到系统内存多少的时候,再有磁盘写操作时开始向磁盘写出数据。
3 a5 a* ?6 a6 ~7 {" _* Y; u增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。: r7 Z5 s( E5 K! w; ~; c6 o$ g
但是,当你需要持续、恒定的写入场合时,应该降低其数值.
, q! l( q7 v7 K& W/ Z8 t一般缺省是 40。: _( |6 x( j9 n; c
设置方法如下:3 }& D7 r- g- r5 r1 N! @
echo 30 >/proc/sys/vm/dirty_ratio
! T2 y# [" }  m: Y" A9 f5 o' [0 h1 u9 M  e4 _8 M- Y
2. /proc/sys/vm/dirty_background_ratio- P9 m" E0 Z7 |  N% H- k8 H
这个参数控制文件系统的pdflush进程,在何时刷新磁盘。单位是百分比,表示系统总内存的百分比,7 E2 n, _9 ?- ^: L) c: f. p
意思是当磁盘的脏数据缓冲到系统内存多少的时候,pdflush开始把脏数据刷新到磁盘。5 m" Y# @- l7 _: ^3 {  [5 y
增大会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
2 \+ V, o6 q4 x$ p但是,当你需要持续、恒定的写入场合时,应该降低其数值.
3 s% S2 n: a1 U0 c3 z5 M9 B一般缺省是10。1 n3 E' I5 F( [. C, K
设置方法如下:
. @1 V" }' c6 `2 b8 recho 8 >/proc/sys/vm/dirty_background_ratio0 Q$ e  f6 V/ V7 [1 C& o
/ w% V; R# ?4 P0 I+ l
3. /proc/sys/vm/dirty_writeback_centisecs
! d( r% I+ s+ c) WPdflush写后台进程每隔多久被唤醒并执行把脏数据写出到硬盘。单位是 1/100 秒。3 N7 z* w7 U' S* i: m
如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。' P$ m* n/ k* }7 d! l9 Q
缺省数值是500,也就是 5 秒。2 y  X( N: V$ F  p0 [1 e$ L- w9 O' m
设置方法如下:
, W1 J' n' ?6 F- ?4 f# echo 200 >/proc/sys/vm/dirty_writeback_centisecs
7 B1 M# @9 r3 k  R  S
! M- o3 y3 W$ Q% v! k7 u4. /proc/sys/vm/dirty_expire_centisecs
% t" [5 e" d) a& c* [这个参数声明Linux内核写缓冲区里面的脏数据多“旧”了之后,pdflush 进程就开始考虑写到磁盘中去。4 }0 A- ]; y* w' k" q4 _5 E6 P
单位是 1/100秒。
5 n  O; T+ s2 d对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。) l4 B5 m' p- V2 |. M7 Y
缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新磁盘。9 V" _- v1 k, U* v6 h
建议设置为 1500,也就是15秒算旧。" K+ _1 O+ h* J# l
设置方法如下:8 V8 i8 f1 Z' @* K2 y. m
echo 1500 >/proc/sys/vm/dirty_expire_centisecs
- |) l8 b2 f$ L: H# ?
  f. x! h( A/ S# @1 w# j/ r三、内核参数修改后的生效# J3 z$ g/ f" t$ a
Linux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统,
9 w. t* T; _& q- `* m: E- Z这个功能是通过/proc虚拟文件系统实现的。* W3 K# i4 q# w- U
6 q( ]3 h+ L% g- c. g+ d1 b) j
在/proc/sys目录下存放着大多数的内核参数,并且设计成可以在系统运行的同时进行更改,
+ ?$ g6 S# ^( n$ e1 L# I1 y可以通过更改/proc/sys中内核参数对应的文件达到修改内核参数的目的(修改过后,保存配置文件就马上自动生效),
# r0 K: w5 y! F不过重新启动机器后之前修改的参数值会失效,所以只能是一种临时参数变更方案。
5 s# e6 u' B5 ](适合调试内核参数优化值的时候使用,如果设置值有问题,重启服务器还原原来的设置参数值了。简单方便。)
: [( B" @8 ^4 h, s! d! u/ ]# A
  J+ M; [3 H  R/ _* {但是如果调试内核参数优化值结束后,需要永久保存参数值,, b; J$ r  R' n: J1 J; F1 C
就要通过修改/etc/sysctl.conf内的内核参数来永久保存更改。( \, D( j6 F+ Y. \+ R
但只是修改sysctl文件内的参数值,确认保存修改文件后,设定的参数值并不会马上生效,% H% g- c: ?5 e) ]' E4 d- t
如果想使参数值修改马上生效,并且不重启服务器,可以执行下面的命令:
. f# x; L8 E2 {* Z. p- \  # sysctl –p
) ]5 K  h% d5 t4 O7 b% e' i
4 U0 b( X6 l5 V4 ~下面介绍一下/proc/sys下内核文件与配置文件sysctl.conf中变量的对应关系:
: k! A6 X. y# G* j2 F$ V. _+ t9 {/ i/ F由于可以修改的内核参数都在/proc/sys目录下,所以sysctl.conf的变量名省略了目录的前面部分(/proc/sys)。
; K# G% p' t6 i1 }& Y3 o即将/proc/sys中的文件转换成sysctl中的变量依据下面两个简单的规则:6 F1 d7 I# p, {3 Y
1.去掉前面部分/proc/sys
4 n' S- m, z, C4 N2.将文件名中的斜杠变为点- s6 X& T- u+ d

+ v5 i% S2 f: r9 j+ R$ B这两条规则可以将/proc/sys中的任一文件名转换成sysctl中的变量名。3 H* _- j' D) a! U: `* w4 {: s
例如:
" g: I: Q) ]$ A% z/proc/sys/net/ipv4/ip_forward =》 net.ipv4.ip_forward" c, E! `" H9 x3 h
/proc/sys/kernel/hostname =》 kernel.hostname; ?- u0 L' K" w$ |" E" v. |

  y! c7 Z7 G' I( ^& s+ k* G/ b可以使用下面命令查询所有可修改的变量名7 H& X* k- b6 R" l" \. O  i6 I, y
  # sysctl –a
+ K3 a3 I, A+ Q7 s8 n% |0 I
# e6 o; Q* j5 o  L! `
7 D0 i1 Z; n: s! j8 m  V: C3 g  f
作者: CCxiaom    时间: 2020-4-17 18:37
pdflush进程详解
作者: ExxNEN    时间: 2020-4-20 13:26
pdflush进程详解




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2