当前位置:嗨网首页>书籍在线阅读

10-信号与exec()

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

27.5 信号与exec()

exec()在执行时会将现有进程的文本段丢弃。该文本段可能包含了由调用进程创建的信号处理器程序。既然处理器已经不知所踪,内核就会将对所有已设信号的处置重置为SIG_DFL。而对所有其他信号(即将处置置为SIG_IGN或SIG_DFL的信号)的处置则保持不变。这也符合SUSv3的要求。

不过,遭忽略的 SIGCHLD 信号属于 SUSv3 中的特例。(之前曾在 26.3.3 节提及,忽略SIGCHLD能够阻止僵尸进程的产生)。至于调用 exec()之后,是继续让遭忽略的 SIGCHLD 信号保持被忽略状态,还是将对其处置重置为 SIG_DFL,SUSv3 对此不置可否。Linux 的操作取其前者,而其他一些UNIX实现(如:Solaris)则采用后者。这就意味着,对于忽略SIGCHLD 的程序而言,要最大限度的保证可移植性,就应该在调用 exec()之前执行 signal(SIGCHLD,SIG_DFL)。此外,程序也不应当假设对SIGCHLD处置的初始设置是SIG_DFL之外的其他值。

老程序的数据段、堆以及栈悉数被毁,这也意味着通过sigaltstack()(21.3节)所创建的任何备选信号栈都会丢失。由于 exec()在调用期间不会保护备选信号栈,故而也会将所有信号的SA_ONSTACK位清除掉。

在调用 exec()期间,进程信号掩码以及挂起(pending)信号的设置均得以保存。这一特性允许对新程序的信号进行阻塞和排队处理。不过,SUSv3 指出,许多现有应用程序的编写都基于如下的错误假设:程序启动时将对某些特定信号的处置置为 SIG_DFL,又或者并未阻塞这些信号。(特别是,C语言标准对信号的规范很弱,对信号阻塞也未置一词,所以为非 UNIX系统所编写的C程序也不可能去解除对信号的阻塞。)为此,SUSv3建议,在调用 exec()执行任何程序的过程中,不应当阻塞或忽略信号。这里的“任何程序”是指并非由 exec()的调用者所编写的程序。至于说如果执行和被执行的程序均出自一人之手,又或者对运行程序处理信号的手法知根知底,那自然又另当别论。