Unix编程艺术:多道程序设计

简介:
多道程序设计:分离进程为独立的功能

Unix的最具特点的程序模块化技法就是将大型程序分解成多个协作进程。

Unix提倡把程序分解成更简单的子进程,并考虑接口:
降低进程生成的开销。
提供方法简化进程间通信。
提倡使用能由管道和套接字传递的简单、透明的文本数据格式。

真正的挑战不是协议语法而是协议逻辑:协议设计既要有充分的表达能力,又能防范死锁。

从性能调整中分离复杂度控制

在开发出可以把全局复杂度降至最低程度的干净体系之前,关注性能问题便是过早优化。

线程提高了复杂度,应尽量少用线程。

将程序划分为多个协作进程的另一重要原因是提高安全性:仅信任较少的代码,而让大部分操作都运行在用户级。

Unix IPC方法

1 把任务转给专门程序。

廉价的进程生成使得程序间协作变得可能,通过调用专门程序来完成专门任务;
C库popen可以用来向专门程序传递数据或读取专门程序的返回结果;
专门程序运行期间并不需要与父进程交互。

示例:
mutt:调用专门的编辑器。

2 管道、重定向、过滤器

管道: |把一个程序的输出连接到另外一个程序的输入;单向性;管道中所有程序并发执行;匿名管道,命名管道(为命名套接字取代)。
重定向:> <
pic2graph:调用现有工具的管线。
dc和bc:相互组合完成问题。
fetchmail:不能使用,因为管道的单向性;不能发出反馈信息。

3 包装器
脚本中封装命令的固定参数

4 安全性包装器

安全性包装器:调用专门程序检查某类凭证,然后根据返回结果执行后一个程序;
bernstein链与管道类似;只不过每个继发阶段的程序取代了前一阶段的程序,而不是与之并行。

5 从进程

主从通信很复杂,只有在协议无关轻重。

6 对等进程间通信

临时文件:简单,灵活,但容易引起名字冲突,提前中断会造成问题;文件容易被修改,安全问题;
信号:软中断,SIGHUP一般被用作重启初始化,而用SIGTERM作为正常退出的信号;
pidfile:守护进程只允许一个实例运行,则可作为文件锁使用。
fetchmail信号:唤醒已经存在的进程或者新建进程来获取邮件。

套接字:双向IPC
PostgreSQL:客户端和服务器端分开。

共享内存:速度快,只用在同一机器上。mmap,将文件映射到内存。自己处理竞争和死锁;避免通过网络栈复制数据的开销。

要避免的问题和方法

复杂的结构比文本流难以处理。RPC提供了丰富接口,但恰恰将问题复杂化了。
文本流:性能损失是线程的,但可通过硬件升级来补偿。
XML-RPC和SOAP综合了文本流和RPC方法的优点。

线程

局部变量共享全局内存使得需要加入竞争和临界区的控制,同时bug也会增多。
时序依赖问题
尽管线程没有进程上下文切换的开销,但锁定共享数据结构的开销同样昂贵。
客户端/服务器划分:由服务器集中管理所有资源争用,降低了复杂性,也有利于适应分布式计算。
把线程、远程过程调用接口和重量级的面向对象设计结合使用特别危险。


真实世界里的编程其实就是管理复杂度的问题。能够管理复杂度的工具都是好东西。但当这些工具不是控制而是增加复杂度的时候,最好扔掉,从零开始。

本文转自feisky博客园博客,原文链接:http://www.cnblogs.com/feisky/archive/2012/01/31/2333990.html,如需转载请自行联系原作者

相关文章
|
Unix Linux C语言
计算机操作系统实验一 Unix/Linux编程开发环境
计算机操作系统实验一 Unix/Linux编程开发环境
158 0
|
17天前
|
算法 Unix 数据安全/隐私保护
Python编程--UNIX口令破解机
Python编程--UNIX口令破解机
22 1
|
4月前
|
Unix
Unix环境高级编程(第三版)中apue.h头文件及其依赖安装教程
Unix环境高级编程(第三版)中apue.h头文件及其依赖安装教程
|
11月前
|
Unix Shell Python
unix高级编程-fork和execve
unix高级编程-fork和execve
53 0
|
11月前
|
Ubuntu Unix Shell
unix高级编程-fork之后父子进程共享文件
unix高级编程-fork之后父子进程共享文件
57 0
|
11月前
|
Unix Linux
unix高级编程-僵尸进程和孤儿进程
unix高级编程-僵尸进程和孤儿进程
55 0
|
11月前
|
Unix Linux 调度
unix编程-fork
unix编程-fork
57 0
|
Unix
Unix高级环境编程
[07] Unix进程环境==================================1、 进程终止    atexit()函数注册终止处理程序。    exit()或return语句:        终止处理程序->终止处理程序->标准I/O清除->_exit()->进入内核。
920 0