|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
多道程序设计:分离进程为独立的功能
) e9 g3 j2 K6 @" o5 r M6 t# D" B# q ~8 k4 B! ^9 f! v& ` l; e
* O1 Z+ Z' I7 p$ N
Unix的最具特点的程序模块化技法就是将大型程序分解成多个协作进程。. C* I; d5 @ |/ b2 M( C
8 L( P4 w) P# f+ x& ^6 Z$ A% n t, b; Q' V
Unix提倡把程序分解成更简单的子进程,并考虑接口:7 ]1 X) H8 P# M) h
降低进程生成的开销。3 s& O2 _/ ~: K+ U( h# w R
提供方法简化进程间通信。
$ H8 ~9 F" J7 v6 r7 ]# D提倡使用能由管道和套接字传递的简单、透明的文本数据格式。
, ~5 }; b$ `; ]7 |/ U9 ~ # H$ u7 M3 E* i) U, |- C5 G7 ~4 Y
# [3 h D0 t7 A, F2 k真正的挑战不是协议语法而是协议逻辑:协议设计既要有充分的表达能力,又能防范死锁。5 v! H9 X# q/ A
: M. g# M- S9 K5 o
/ O! ^, Q) W7 [; q+ B7 m* w- f! |从性能调整中分离复杂度控制
& S5 D8 J, ^3 n$ ?3 K7 h/ j% T% B
" W$ a% [/ S0 F$ \0 I# c- W3 r; n% i6 T3 u2 i: S& h4 b
在开发出可以把全局复杂度降至最低程度的干净体系之前,关注性能问题便是过早优化。8 q4 H# j5 {- ]" J+ v+ h- Z. D
* P& n; R! t# i
) Z7 w& e# D! @0 G
线程提高了复杂度,应尽量少用线程。
! H L+ h4 f" l$ ]
* m$ F ]4 t$ R n& B$ I, U m. f& |' w! L( |: x
将程序划分为多个协作进程的另一重要原因是提高安全性:仅信任较少的代码,而让大部分操作都运行在用户级。' P3 |% _" C( d7 ~, D5 B
, U( {! B+ Q+ o' K; `0 n6 n
( M' s, A( V9 u" I! [- j4 w. x. xUnix IPC方法 H% _' N% q( s- K J
1 h2 S" M& @, y. `5 b7 b0 p( g
. V y5 B0 k: s( S/ Z' y2 V* k
1 把任务转给专门程序。- W' J2 [9 Y7 o9 c
' W/ E& F" ?: }7 l5 j. y( s2 K
: M9 W* v1 ?# P ^: F- b廉价的进程生成使得程序间协作变得可能,通过调用专门程序来完成专门任务;% t0 X8 g2 ?. Q
C库popen可以用来向专门程序传递数据或读取专门程序的返回结果;
8 |# _/ f2 u5 `2 ^专门程序运行期间并不需要与父进程交互。
# L/ b$ U' x a6 x1 h5 V2 W* P! K2 }& F2 j- ~% S0 \# _" G
; Q# i6 F" f) U示例:
1 f( m- g. V6 qmutt:调用专门的编辑器。1 X- v0 D' w. l9 d* T7 ?& c
# w' d$ A; D1 g9 A! R1 V
0 Q- U0 E; _: C0 v
2 管道、重定向、过滤器
; h* G. L8 ^2 x* P8 a N, ~: W+ l; y( P" o# D4 W
6 L. C2 K7 t( e j, y/ k0 K5 e
管道: |把一个程序的输出连接到另外一个程序的输入;单向性;管道中所有程序并发执行;匿名管道,命名管道(为命名套接字取代)。. D" P) H0 T& i& B P" @- |, v
重定向:> <& w8 {/ Z9 O! w0 p6 r' U
pic2graph:调用现有工具的管线。$ ~! A- d' D7 i; c* n) M
dc和bc:相互组合完成问题。 d4 A: E7 B6 ^8 T1 n
fetchmail:不能使用,因为管道的单向性;不能发出反馈信息。
$ d( N# W" m3 V! Y* e1 I0 b
3 d( D' v9 Z8 m3 ?* [5 G/ F# Y" `& ~. |! t3 ^6 B) F2 Z% e2 P# [
3 包装器
: C. W" ?+ h8 @) `8 X3 l6 e脚本中封装命令的固定参数
0 T7 a1 h6 R8 G' x, L. ~/ l/ O: A1 o( h( z+ D, z2 h
4 C8 V& {, W' t4 安全性包装器
4 t' s3 y7 w5 U! H) i. p$ }2 X6 [4 r _8 `6 B- J8 i* q {
" p1 Z, F, K: N9 W/ Q/ M
安全性包装器:调用专门程序检查某类凭证,然后根据返回结果执行后一个程序;0 V3 p9 m2 k1 o9 ~ e$ ~, t
bernstein链与管道类似;只不过每个继发阶段的程序取代了前一阶段的程序,而不是与之并行。
5 p/ l1 u" s$ @0 o$ Y
( M2 H$ U. f9 F$ w1 e" |2 d: Q6 O8 g$ M2 G. g( G% A( P
5 从进程
1 \" g. Z9 n8 n! \ l
+ I4 {& u& H3 Q) g2 R' V, ^* O, F) x9 R3 e. W7 {
主从通信很复杂,只有在协议无关轻重。
2 I! N- x! F) V9 s- l; B1 O# s0 s: H5 D! m4 _5 l1 j" V/ p$ m# M
; V9 m" m/ t f6 V% L6 对等进程间通信
. u9 b* L1 @. o: |# P! S! L& D; v0 s: d) X: v6 `
+ d) I* D! h& p+ R1 M9 y G临时文件:简单,灵活,但容易引起名字冲突,提前中断会造成问题;文件容易被修改,安全问题;! @' J; ?) Q& r
信号:软中断,SIGHUP一般被用作重启初始化,而用SIGTERM作为正常退出的信号;
3 E& |. j h5 U! Spidfile:守护进程只允许一个实例运行,则可作为文件锁使用。
& x9 I6 c" \7 s) H2 q* j3 f( wfetchmail信号:唤醒已经存在的进程或者新建进程来获取邮件。
6 G- n' y7 U# i. e/ u' m7 K/ X4 ^0 E, D! p" W/ {4 t& Z
* V5 z& J4 s9 W& U/ e9 f4 h
套接字:双向IPC
. O+ C e6 k( ]. APostgreSQL:客户端和服务器端分开。/ V/ K {$ g) r7 `* [% W- y9 S
7 p2 S" H1 z3 z) x, f! E3 \9 |
* c1 H/ q g. Q7 i- ^ A3 w" u共享内存:速度快,只用在同一机器上。mmap,将文件映射到内存。自己处理竞争和死锁;避免通过网络栈复制数据的开销。
9 t+ A+ [: O% w$ Z4 w* t' I. p/ N1 L
0 r2 y( s3 h0 t- k" I要避免的问题和方法8 q8 E. I! D3 j
+ h' R' `6 ?) E1 W' U# k( N
) F9 @" h% h% G6 S复杂的结构比文本流难以处理。RPC提供了丰富接口,但恰恰将问题复杂化了。; D7 ?( C3 X( \9 g" @4 _# h
文本流:性能损失是线程的,但可通过硬件升级来补偿。0 M+ P$ D3 R$ [) z! @
XML-RPC和SOAP综合了文本流和RPC方法的优点。( E$ \0 W# n( U2 b: d: c
% g$ `* e2 `9 l5 x/ ~3 @' z3 x
2 z) |* ]' m- W线程
# i/ r! _* M$ D8 u$ m. l& h. m( o
+ q' q7 k8 c/ b局部变量共享全局内存使得需要加入竞争和临界区的控制,同时bug也会增多。
& a* ~4 d. E3 m3 Q8 Y时序依赖问题$ A J5 e; a0 _2 B; v! f
尽管线程没有进程上下文切换的开销,但锁定共享数据结构的开销同样昂贵。# l H; }& K3 l/ K; [/ ~
客户端/服务器划分:由服务器集中管理所有资源争用,降低了复杂性,也有利于适应分布式计算。3 s' C. A& y. e5 r/ D+ B+ w# z3 I
把线程、远程过程调用接口和重量级的面向对象设计结合使用特别危险。
& Q1 l0 W0 m C) d) H* I$ B" w" t. e1 a: s
+ C" E* G6 B% L( t0 C1 g* b9 ~" [: y1 W% _9 P$ x$ U: W1 V4 s: m* n
8 y; L( M" p* T6 Z& E
真实世界里的编程其实就是管理复杂度的问题。能够管理复杂度的工具都是好东西。但当这些工具不是控制而是增加复杂度的时候,最好扔掉,从零开始。5 W+ J) L: `! x- T/ P5 c
. J3 ^% G& F4 K+ X4 l3 _; k8 ~
$ t% k2 N$ o- _
n L' J# B4 y% e1 r
5 z4 ^# {# u% g5 z0 @: z) m
! c5 r2 H* f$ ?# E' ^7 P |
|