随笔 - 119  文章 - 290  trackbacks - 0

博客搬家了哦,请移步
叫我abc

常用链接

留言簿(12)

随笔分类

我的博客

搜索

  •  

积分与排名

  • 积分 - 301934
  • 排名 - 84

最新评论

阅读排行榜

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 阅读(2300) 评论(8)  编辑 收藏 引用 所属分类: 《UNIX编程艺术》读书笔记

FeedBack:
# re: IPC,读《Unix编程艺术》某章感 2006-08-14 17:19 yifeng
首先谢谢你的文章。
你说的这一段书,我也有看,但存在疑问。

线程A发生内存溢出,可能会波及到线程B。
或因为线程A的错误,使程序崩溃,连带波及线程B。
这些意外状况,是我唯一想到的差别。
(还有你说的开发过程中难调试的问题)

除此,我没想到实际差别。
任务逻辑解耦得好,和使用进程或线程没有关系
如果一个进程的运行完全不需要和另一个进程通信,
那么设计出来的线程任务也一样不需要通讯,反之亦然。

一般,使用对象,能把线程任务封装得很好,输入和输出清晰。
两个进程使用共享内存,也需要保护,其情况和线程间共享数据结构无异。

所以我不能理解把“时序问题、竞争/死锁问题”归为线程带来问题。

为此我想到了一种解释,就是进程模型喜欢使用耦合度更低的通讯模式,例如Socket,
而用线程的人则一般不愿意这样做,而是直接回调,共享数据结构。
不是因为线程模型比进程模型会带来复杂,
而是因为选用了不同的通讯手段,导致复杂性不同。  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2006-08-14 19:35 LOGOS
呵呵.怎么说呢.
讨论IPC,就说明讨论的是需要通讯的任务(进程/线程).
线程与进程的本质区别,应该是地址空间问题.进程是独立的,线程是共享的.
UNIX的元老们最害怕的应该就是没有隐私吧.
线程的通讯方式通常是共享数据结构(全局变量),全局变量是单份的,线程们要使用的话,必须竞争.如果线程过多,资源的分布过分复杂,也许会有意想不到的死锁问题.通常死锁....谁能预见呢?
至于时序问题,其实在大学有认真学习过"操作系统",都知道怎么完美的控制各个任务的执行时序的.
的确,不能说“时序问题、竞争/死锁问题”归为线程带来问题,不过这两个问题领域,似乎是在线程编程的时候才显得尤其突出的.

使用对象的确能把线程封装得很好,不过这种很好,仔细想想,是对于不需要通讯的线程很好吧.只要用全局变量进行通讯,还是会绕回原来的点上.

另外,将任务做成进程而不是线程还基于这样一个理由,重用.
虽然说线程的代码包装得好,可以像一个类库一样重用.但是一个进程的重用,是在编译成一个执行文件之后,用批处理调用的重用.
你觉得是一个类(包含不少接口,并且有调用顺序/环境之类的约束,要命的是好像它还是线程)重用得顺手,还是像"SomeTast.exe -SomeParam"这样在主程序中执行bat命令舒坦呢?
因人而异吧.

并没有反对线程的意思.只是想说,能用简单的先用简单的吧.下班越早越好,是吧.  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2006-08-15 11:37 yifeng
啊,别误会,没有说谁反对线程或进程的意思。
只是单纯的探讨。

我认为只要有并发和竞争就会有死锁的可能,进程也不例外。
我最大的疑问是,我假想不出具体的情形,能说明线程遭遇的问题比进程更突出。
而我只能理解为"他们使用了不同的通讯手段"

我的工作语言是C++,线程共享的一般不会是全局对象,而是局部的。
在创建线程任务时,让他们持有共享对象的句柄。
目前为止,我未发现在控制他们的生命周期上有困难。
所以也没有发现使用全局对象的必要。

但,一般我会在资源上使用大粒度锁,假如我没有发现功能或性能上有细化的必要。
这也就尽量避免了拿到了叉子等刀子的情况。
线程过多,资源的分布过分复杂的情况,的确很难控制。
但也使我怀疑这种情况下使用进程模型是否合适。
  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2006-08-15 12:43 LOGOS[offline]
和你讨论线程,我有点心虚.因为我对线程仅限于概念性认识而已.
你说"在创建线程任务时,让他们持有共享对象的句柄。", 这个"共享对象句柄"不是全局的吗?我猜你的意思可能是他们的生命周期处于一个局部过程内,但是会比持有他们线程要长,也就是主函数内.那么我想拓展我所说的全局的意思,广义上,凡是被多个线程竞争的变量,其意义都和全局变量无异.
事实上,我所在意的也就是线程竞争变量的问题.因为那些变量用于通讯.

对于资源分布复杂,我觉得这对进程没有多大影响.因为在讨论线程的时候,所谓的资源只是简单的指那些被竞争的变量.对于进程而言,通信的数据都是以副本存在的.可能你的意思是像文件之类的资源,这种资源属于硬件资源,由于本身的有限性,无论如何也都要竞争啦.

应该说,线程一样可以很好的编程,很好的工作.但是UNIX文化中极力提倡程序是可以脚本化的(也就是批处理文件那样子),以便于复用.这一点线程好像没什么办法可以做到哦,再加上不统一的API问题,所以也就不怎么被推荐.
此外,考虑到本书作者是一个愤青(译者说),彻底的反GUI,反二进制的家伙,偏见也就不足为其了.  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2006-08-15 12:46 LOGOS[offline]
PS:进程在管道模型下,脚本包装模型下,可以认为是顺序工作的.在套接字下是并发工作. 同时独立的地址空间.
而线程一开始就是并发,而且共生共用的.  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2006-08-16 10:20 lingate
所谓的"彻底的反GUI,反二进制的家伙",实在言过其实了,因为作者一再强调界面和策略相关,而且在例子中作者推荐了一款业余人员特别喜欢的发送邮件的软件,作者就认为界面设计很好,即照顾了普通用户的需要又很好的显示程序的状态。在后面的大量篇幅中作者一直在说明程序编写需要简单性与透明性,也是一个标准的以人为本的思路,译者的一家之言,请不要因此用带色眼镜看他。  回复  更多评论
  
# re: IPC,����Unix���������ij�¸� 2007-08-10 18:36 xmlscript@hotmail.com
������ڱ�дһ��webserver��Ϊ���㣬����windows�ﹹ��������Ŀ����unix�汾������Ȼ��Ҫʹ�ö��̣߳��������б�ʾunix������ö���̣�
���ڶ�unix����֪��������ʹ����ͣ����ͷwin32�Ŀ�����unix�µij������ҵwebserver����δ�����һ��ϵ���أ�  回复  更多评论
  
# re: IPC,读《Unix编程艺术》某章感 2007-08-10 18:37 xmlscript@hotmail.com
我最近在编写一个webserver,为方便,先在windows里构件,最终目的是unix版本。很自然我要使用多线程,但你文中表示unix下最好用多进程?
由于对unix的无知和向往,使我暂停了手头win32的开发。unix下的成熟的商业webserver是如何处理这一关系的呢?  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理