Posted on 2008-06-01 20:27
lymons 阅读(1359)
评论(0) 编辑 收藏 引用 所属分类:
C++ 、
C 、
Unix/Linux 、
文章翻译
■[C++] UNIX上的C++程序设计守则(1)
原文:http://d.hatena.ne.jp/yupo5656/20040712/p1
Unix跟Windows等那些”对于开发者易于使用”的OS比起来,在信号和线程的利用方面有诸多的限制。但是即使不知道这些知识就做构架设计和实现的情况也随处可见。这个就是那些经常不能再现的bug的温床吧。
因此,我想分成几回来写一些准则来防止陷入到这些圈套里。
准则1:不依赖于信号收发的设计
·给其他进程以及自己发送异步信号并改变处理流程的设计不要做
- 异步信号是值用kill系统调用来创建?发送的信号、例如SIGUSR1,SIGUSR2,SIGINT,SIGTERM 等
- 简单的使用忽略信号(SIG_IGN)则没有问题
·不要把线程和信号一起使用
说明:
同步信号是指,因为某些特定的操作*1而引起向自身进程发送某些特定的信号,例如SIGSEGV,SIGBUS,SIGPIPE,SIGSYS,SIGILL,SIGFPE。异步信号就是这些以外的信号。在什么时机发送异步信号并不能被预测出来。我们会在程序里追加收到某些信号时做一些特殊处理(信号处理函数)的函数。那么根据收到的信号就跳到信号处理函数的程序就叫做”在任意代码处都能发生跳转”的程序。这样的程序往往隐藏这下面的那些问题:
- 容易引入BUG。”任意的代码”虽然也包含”执行C/C++里面的一条语句的过程中”的意思,但这很容易跳出程序员的正常思维以及默认的假定条件。编写程序的时候往往需要考虑比C++异常分支还要多得多的分支情况。
- 使测试项目激增。即使根据白盒测试达成100%的分支覆盖,也不能网罗到因为接受信号而发生的跳转分支处理。也就是说做到100%的网罗信号跳转分支的测试是不能全部实现的。一般的,加上要考虑” 在实行某个特定代码时因为接受到信号而发生的误操作”这样的BUG会经常发生*2的这种情况,测试困难往往就是导致软件的品质低下的诱因。
根据经验,”当检查到子进程结束(接收到SIGCHLD信号)时,要做必要的处理”像这样的信号处理不管做什么都是有必要的情况会有,但是除此以外的信号处理,例如
- 把自己的状态用信号告诉其他进程
- 主线程在输入输出函数里发送信号给被阻塞的子线程,并解除阻塞
等,是应该事先好好好好考虑过后再去做实际的实现。前者的话,如果不强制在”普通的”进程间进行通信的话可能会很好,后者是特意要使用线程,也要应该按照即使阻塞了也不能发生问题那样再设计。
不管怎么样,如果必须要使用信号的话,也要先全部*3理解这些陷阱以及,和多线程软件设计的场合一样或者说比它更严格的制约.注意事项都需要铭记在心里。
*1:例如,引用空指针
*2:参照 id:yupo5656:20040703 的sigsafe说明
*3:暂时先掌握”准则2”:-)