|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
多道程序设计:分离进程为独立的功能4 |& }# b; j* `' p* I& l0 M
8 ]+ l* f5 t# }- E
/ U/ A. j' U/ Q- v2 R0 pUnix的最具特点的程序模块化技法就是将大型程序分解成多个协作进程。
( L$ G% \* K' c
# \9 t, K a% J" [- q- @; j2 W; g% O) C) q3 p9 ^- Y H/ z9 m# W
Unix提倡把程序分解成更简单的子进程,并考虑接口:; Z0 O6 \( p: Y' @! d
降低进程生成的开销。
! S% e9 o T$ v2 B提供方法简化进程间通信。
; p& q' j* Z$ L: a8 {( ]" U提倡使用能由管道和套接字传递的简单、透明的文本数据格式。
& ?8 ]+ G; [- p* L# w( a3 E X! o
9 H0 F( O8 p+ k; A: P3 v
: j1 `* J. I/ d) Q真正的挑战不是协议语法而是协议逻辑:协议设计既要有充分的表达能力,又能防范死锁。4 o9 h0 A9 d9 y. C) ]! O, u( ~
$ N, D; Y/ Z- x3 j
# h f) }6 A/ a3 M5 w1 q
从性能调整中分离复杂度控制
) F5 m8 L# R1 e7 N9 V) a8 U: ?5 i; L0 J% m6 D
) W7 p: l8 m9 W M" r, R7 ~4 H
在开发出可以把全局复杂度降至最低程度的干净体系之前,关注性能问题便是过早优化。
+ b3 l( ^8 Y; ] V: P' i* |0 \) ]+ w! m( s- X, o
% c6 l% @: S8 L* f
线程提高了复杂度,应尽量少用线程。
) d3 Q- R; K0 E/ j& N1 X7 Y6 x c: I3 P
" z( S: E6 f* Y将程序划分为多个协作进程的另一重要原因是提高安全性:仅信任较少的代码,而让大部分操作都运行在用户级。
: H8 A; u6 h. G& |9 ~1 A$ n. y% h; N: E+ f' f( j5 v( {
( Y9 K! F% |7 R4 H( J* i8 UUnix IPC方法" ~& {, r$ u% t+ m8 e! }# l
; D% J$ I" [* H! @
" j9 ? Z" r) M9 K1 把任务转给专门程序。' c8 ^3 u; u) f1 I
+ p4 r* I% n" A" Y6 _( T! [, ?- S4 L1 n( L! _, @
廉价的进程生成使得程序间协作变得可能,通过调用专门程序来完成专门任务;0 o: r) l& E% ]8 v; C
C库popen可以用来向专门程序传递数据或读取专门程序的返回结果;( {+ i4 z/ p/ j# [+ \1 E5 {+ R
专门程序运行期间并不需要与父进程交互。* ~- z0 z- w' [. @8 S0 {
- w/ E) `8 Q; ]) w# e0 W
6 w, A1 M B/ ~' N- E示例:
% k7 q; {$ h5 B" i* F3 q0 pmutt:调用专门的编辑器。, C# C& O( a, U5 V0 V4 |5 ]
) r" N( m6 j, r' D9 u' c) ^
5 X/ d9 l# R/ i/ H9 m
2 管道、重定向、过滤器! i( {, ~* C C; D
0 f& \- m) H4 f% j# Q
8 ]" @2 g5 G. F5 y L- W2 b& t9 D t管道: |把一个程序的输出连接到另外一个程序的输入;单向性;管道中所有程序并发执行;匿名管道,命名管道(为命名套接字取代)。$ I# `8 O" |3 ?& M4 E0 ~- K
重定向:> </ I& G+ a! n. m( [
pic2graph:调用现有工具的管线。
0 u) t0 @7 w. A T. z# Ldc和bc:相互组合完成问题。
7 x! m8 H: e8 Y6 \fetchmail:不能使用,因为管道的单向性;不能发出反馈信息。
$ n5 M5 s9 }: P1 \3 ~( g1 _- j! I, c8 ~
' h% w3 n6 j9 M- W7 P
3 包装器3 } x( |9 u7 G% d
脚本中封装命令的固定参数
- @, _. _, q# W: t! x2 s+ q* \3 C% I
/ w0 }6 y; Y. |- P5 a( N4 安全性包装器
' u/ V4 M+ j4 l, F, x X" S* C2 M+ a& U* l6 {
& s" }8 m+ d" K; o; w
安全性包装器:调用专门程序检查某类凭证,然后根据返回结果执行后一个程序;
5 `$ G( v+ t* O$ F0 ], t& J+ wbernstein链与管道类似;只不过每个继发阶段的程序取代了前一阶段的程序,而不是与之并行。
& r. A- S" V" |& s5 x ?% e) \/ [2 B* ?1 |
) o b/ c9 K6 h/ t( b# X [+ z
5 从进程
: X D9 O$ B" H V1 C$ O5 h3 G6 i" n( d) o0 B; E2 C& L
$ _! [/ S4 D+ {' S+ R2 c主从通信很复杂,只有在协议无关轻重。4 Q, F8 X5 F$ H/ j$ J- l7 R1 @
$ Z' Z* ^* H* x2 Z( w4 ?2 L; @
; R. U4 o* v; X- R6 对等进程间通信
. V5 u8 [ I% l. z+ o8 e" y R. j1 ~* y( M6 Y4 Y
- y! P+ X, H/ M0 w X/ i4 e
临时文件:简单,灵活,但容易引起名字冲突,提前中断会造成问题;文件容易被修改,安全问题;
6 D4 R V0 c* w" S0 L% k( N+ }信号:软中断,SIGHUP一般被用作重启初始化,而用SIGTERM作为正常退出的信号;
& N* k! V% l6 {0 t1 K apidfile:守护进程只允许一个实例运行,则可作为文件锁使用。+ f G) s9 e7 ?6 Y) |! E
fetchmail信号:唤醒已经存在的进程或者新建进程来获取邮件。+ O o0 {6 x9 P. w
! g6 h) f# \- E0 E) M! h( _ a9 t" ]( T" J
* P# ^7 w1 S( Y8 c$ z套接字:双向IPC8 \8 M5 U* f- w" I% E! }+ E* _% i
PostgreSQL:客户端和服务器端分开。
. w. P* |9 ~4 w' G, G2 B% ~4 G. J. f. l9 U! r, M
- E' M4 b0 o- h8 G
共享内存:速度快,只用在同一机器上。mmap,将文件映射到内存。自己处理竞争和死锁;避免通过网络栈复制数据的开销。! P) m/ L( ~+ L, v, l* ^. }
/ Y$ M0 t( O7 B9 t' E
' l" m& _2 ?2 k6 I3 R9 H要避免的问题和方法+ ?- j& t3 a @
8 ?. R3 e' l# l' s) v& b: X- ~; p+ Y% c8 K [
复杂的结构比文本流难以处理。RPC提供了丰富接口,但恰恰将问题复杂化了。
5 f0 D! A* G8 F0 A文本流:性能损失是线程的,但可通过硬件升级来补偿。
/ V2 M- S. t6 K6 BXML-RPC和SOAP综合了文本流和RPC方法的优点。$ b) { W8 ]. m9 J* e
$ X$ Q+ A( K: ^/ ]% g0 u- U
( [& N% K( j6 ]. V2 b Y+ y
线程
5 n. f" s8 {. V/ [) _% o, J8 i4 s* Z) I7 }4 u3 T
' c. ?5 ~- p* \! c局部变量共享全局内存使得需要加入竞争和临界区的控制,同时bug也会增多。
y) J3 R+ U. J* R. h% T7 y时序依赖问题
1 ~8 `6 `5 M' j6 H, e" E5 [尽管线程没有进程上下文切换的开销,但锁定共享数据结构的开销同样昂贵。
+ a6 c' m6 j* l, P客户端/服务器划分:由服务器集中管理所有资源争用,降低了复杂性,也有利于适应分布式计算。
1 n0 s7 Q/ S/ z4 H @; C把线程、远程过程调用接口和重量级的面向对象设计结合使用特别危险。
! E4 @: o& ?! x2 y4 W7 ?8 Z6 g' v. o% m1 b/ E
5 Q+ Y3 V/ X4 g- _
5 S/ p6 n" N: o# a
1 N3 z. }% ?- B3 |+ {+ F& F真实世界里的编程其实就是管理复杂度的问题。能够管理复杂度的工具都是好东西。但当这些工具不是控制而是增加复杂度的时候,最好扔掉,从零开始。6 ?( \7 n2 Y) f6 I
: Q7 u9 `. r/ t/ e( c& R6 T* W5 {- \& g/ A- V4 Z3 P
. Y# _0 G8 A1 x0 q) @! x/ ~6 c1 _ f/ P; _
. e; @2 g M; Z: h) G0 { |
|