UNIX文化,提倡的是一种简洁,直观,低复杂度的文化.
UNIX倡导多进程编程,而不是大家所熟悉的多线程编程.
由于进程有自己独立的地址空间,因此多进程之间的协作与交互,通关操作系统提供的各种IPC方法实现.
在讨论IPC的那个章节里,提出了管道,信号,临时文件,共享内存,套接字几个模型.
我一般写东西玩的时候,总是喜欢建立控制台程序,因为输入输出库都比较简单,并且所见即得.管道/重定向之类,都是建立在标准输入/输出的基础上.这里所描述的管道/重定向,并不是在一个进程中调用CreatePipe,改变管道方向,然后用CreateProcess建立一个子进程.UNIX所用的方式类似于.bat命令,比如 dir | more,用符号"|"连接两个进程的管道.事实上,一般能用上管道/重定向的进程,都是一个过滤器,数据从标准输入进来,经过加工后从标准输出跑掉.因此,管道/重定向技术对于流水线般加工的任务,是一个相当棒的模型.
需要注意的是,使用管道模型的程序,通常数据流/协议(在某个任务下)是单向的.
总体上,在WINDOWS下像UNIX那样使用管道/重定向机制,通常是用C/C++写许多独立但是可以连接的程序,然后用bat的方式,将其按所需任务组合.如果希望在程序中可以像bat那样启动其他进程,只要用简单的system(command)函数就好了,WINAPI通常都是复杂而累赘的.
UNIX下的信号,是对进程发出的,由进程的相应回调函数处理,程序可以重载自己的实现.这和WINDOWS下的消息比较相像,只是WM通常都需要窗口.由于信号/消息能传递的数据都比较薄弱简单,所以这通常作为一种辅助机制,和其他IPC模型共同协作.
临时文件,是一种能解决双向沟通的模型,但是并不利于做复杂的事情,最好的用途是在简单,需要双方沟通,大数据量的情形下.使用方法大概描述为,A进程调用执行某个任务的B进程,B进程将执行结果写入A进程指定的文件,A进程使用该文件.
一个隐患是,一旦破坏程序知道临时文件的位置,就可能破坏该文件.
其实临时文件和接下来所说的共享内存在功能上并无太大区别.唯一不同的是,临时文件所使用的API,都是很容易跨平台的.
共享内存,是一个和操作系统密切相关的IPC模型,作为生产者/消费者系统的一个性能优化的解决方案,其最大的优势便是对大型数据传递所提供的效率.但是,预防竞争/死锁是必须考虑的问题.我觉得,由于共享内存的API通常是专有的,不易于跨平台,所以使用共享内存的条件应该比较严格,必须要在性能需求高和一次数据交换量巨大的情况下才可以考虑,而且,临时文件是一个可以考虑的替代模型.
套接字,是一个直观并且在众多操作系统中广泛使用的模型,不用说也知道是一个好东西了.
在《UNIX编程艺术》中,认为大多数的IPC方法都是可以相互替代的,因此最重要的是选择一个尽可能使系统简单的模型.此外,特别说多线程不该是最先考虑到的方法,而是最后一个.
多线程将子任务糅合在一个程序中,而不是分开,增加了全局复杂度.此外,多线程带来的2个不可避免的BUG:时序问题,还有竞争/死锁的问题.纵然全局变量提升了任务之间的沟通效率,但是通常这种效率都被昂贵的锁定/解锁所抵消了.
特别是,使用多线程的程序所依赖的库,并非都是线程安全的,其中一旦产生的问题,会使得你麻烦重重,特别是,多线程的程序调试......由于时序问题,你自己想想都知道了.
因此,非要使用多线程,理想(意味着不可能存在)的约束是,线程尽量不使用全局变量;每个变量只被一个线程使用;被线程使用的变量不再被主进程使用;线程中不使用static变量.....这种约束,根本没有办法实现嘛.
posted on 2006-08-13 11:06
LOGOS 阅读(2294)
评论(8) 编辑 收藏 引用 所属分类:
《UNIX编程艺术》读书笔记