1.信号介绍

信号是一种软中断,用于通过异步的方式对进程进行事件通知。信号分为实时信号和非实时信号,各个进程对于信号的处理方式不一,处理方式分为三类:忽略,捕捉,执行系统默认动作。进程可以选择屏蔽某个或某些信号。

2.信号屏蔽

SylixOS可以通过sigprocmask函数对某个信号集内的信号进行屏蔽。在信号被屏蔽的期间,进程对所屏蔽的大部分信号不会进行响应,只有解除屏蔽后才会响应。

2.1 sigprocmask函数

sigprocmask函数原型如程序清单 2-1所示。

程序清单 2-1 sigprocmask函数原型

#include<signal.h>

int sigprocmask (intiCmd,constsigset_t *psigset,sigset_t *psigsetOld);

函数sigprocmask原型分析:

1、此函数成功时返回0,失败时返回-1并设置错误号;

2、参数 iCmd是信号集命令;

3、参数 psigset是新的信号集;

4、输出参数 psigsetOld保存先前的信号集。

sigprocmask设置信号屏蔽字时iCmd对应3个命令:

1、SIG_BLOCK:新的信号集以或的形式添加到当前的信号屏蔽字中

2、SIG_UNBLOCK:从当前的信号屏蔽字中删除新的信号集中包含的信号

3、SIG_SETMASK:将新的信号集赋值给当前信号屏蔽字

2.1 sigprocmask函数

SylixOS可以通过四个函数对信号集进行操作,具体函数如程序清单 2-2所示。

程序清单 2-2 信号集操作函数

#include<signal.h>

int sigemptyset (sigset_t *psigset);

int sigfillset (sigset_t *psigset);

int sigaddset (sigset_t *psigset,intiSigNo);

int sigdelset (sigset_t *psigset,intiSigNo);

1、sigemptyset函数用于初始化一个信号集,使其不包含任何信号;

2、sigfillset用于初始化一个信号集,使其包含所有信号;

3、sigaddset用于向一个信号集中添加某个信号;

4、sigdelset用于从一个信号集中删除某个信号。

SylixOS可以设置进程屏蔽任意的信号,但是某些信号即使被设置屏蔽也无法生效,无法被屏蔽的信号如表 2-1所示。

表 2-1 无法屏蔽的信号

信号名

信号描述

SIGKILL

强迫进程结束

SIGABRT

异常结束

SIGSTOP

停止进程执行

SIGFPE

协处理器出错

SIGILL

非法指令

SIGBUS

bus error

SIGSEGV

无效内存引用

2.1 信号屏蔽测试

设置进程屏蔽所有的信号后,向进程发送任意的信号,可以查看到信号是否被屏蔽,具体的信号屏蔽测试代码如程序清单 2-3所示。

程序清单 2-3 信号屏蔽测试代码

#include<stdio.h>

#include<signal.h>

int main (intargc,char **argv)

{

int iSigNo; /* 信号ID */

sigset_t newMask; /* 新的信号集 */

sigset_t oldMask; /* 旧的信号集 */

sigset_t pendMask; /* 阻塞的信号集 */

sigfillset(&newMask); /*信号集包含所有信号 */

/*

* 设置新的信号掩码,并保存旧的信号掩码

*/

if (sigprocmask(SIG_SETMASK, &newMask, &oldMask) < 0) {

fprintf(stderr,"Sigprocmask error.\n");

return (PX_ERROR);

}

sleep(5); /*休眠等待信号 */

sigpending(&pendMask); /*获取未决的信号集 */

/*

* 打印出未决信号集中的信号

*/

for (iSigNo =SIGHUP;iSigNo <=SIGRTMAX;iSigNo++)

{

if (sigismember(&pendMask,iSigNo) ==TRUE) {

fprintf(stdout,"Signal %d pending.\n",iSigNo);

}

}

/*

* 恢复旧的信号掩码

*/

if (sigprocmask(SIG_SETMASK, &oldMask,NULL) < 0) {

fprintf(stderr,"resume mask error.\n");

return (PX_ERROR);

}

return (ERROR_NONE);

}

运行代码后,可以通过kill命令向进程发送除表 2-1以外的任意的信号后,信号无法被响应,运行结果具体如图 2-1所示。

图 2-1 测试代码的运行结果

若发送无法被屏蔽的信号,则会执行与信号相关联的处理动作。

3.参考资料

《SylixOS应用开发手册》