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; ?- E
pdflush就认为这个inode对应的所有脏页的变脏时间都是10秒前,即使可能部分页面真正变脏的时间不到10秒,
: j- [6 r A/ C+ M
细节可以查看内核函数wb_kupdate()。
: r# b! D2 K S p& d( U
7 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! F
pdflush回写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: y
2.4内核中是没有的。
% i3 p+ e: q% y& V6 H t4 Z2 y
+ x7 R0 M( m4 Z8 F6 D. l
4 、用户调用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_ratio
9 ^" 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 f
5 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 r
echo 8 >/proc/sys/vm/dirty_background_ratio
0 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) W
Pdflush写后台进程每隔多久被唤醒并执行把脏数据写出到硬盘。单位是 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 u
4. /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 N
2.将文件名中的斜杠变为点
- 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