在对嵌入式 Linux 系统程序开发中的进程间通信进行学习时,涉及到了信号集函数组,书中给出的示例如下:
该实例首先把 SIGQUIT、SIGINT 两个信号加入信号集,然后将该信号集设为阻塞状态,
并在该状态下使程序暂停 5 秒。接下来再将信号集设置为非阻塞状态,再对这两个信号分别
操作,其中 SIGQUIT 执行默认操作,而 SIGINT 执行用户自定义函数的操作。源代码如下
所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <sys/types.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h>
void my_func(int signum) { printf("If you want to quit,please try SIGQUIT\n"); } int main() { sigset_t set,pendset; struct sigaction action1,action2; if(sigemptyset(&set)<0) perror("sigemptyset"); if(sigaddset(&set,SIGQUIT)<0) perror("sigaddset"); if(sigaddset(&set,SIGINT)<0) perror("sigaddset"); if(sigprocmask(SIG_BLOCK,&set,NULL)<0) perror("sigprocmask"); else { printf("blocked\n"); sleep(5); } if(sigprocmask(SIG_UNBLOCK,&set,NULL)<0) perror("sigprocmask"); else printf("unblock\n"); while(1){ if(sigismember(&set,SIGINT)){ sigemptyset(&action1.sa_mask); action1.sa_handler=my_func; sigaction(SIGINT,&action1,NULL); }else if(sigismember(&set,SIGQUIT)){ sigemptyset(&action2.sa_mask); action2.sa_handler = SIG_DFL; sigaction(SIGTERM,&action2,NULL); } } }
|
理论上,按说明所述及代码的编写,使用 Ctrl-C
传递 SIGINT
信号后,会转到自定义处理函数 my_func
,但在实际操作中,在进入自定义处理函数后,程序直接退出。猜测是由于在进行自定义处理函数后,系统仍然对信号做了默认的处理。
在请教老师后,给出了一种解决方案,对 sigaction
结构体中的 sa_flags
进行赋值,这里先贴出该结构体。
1 2 3 4 5 6
| struct sigaction { void (*sa_handler)(int signo); sigset_t sa_mask; int sa_flags; void (*sa_restore)(void); }
|
sa_handler
是一个函数指针,指定信号关联函数,这里除可以是用户自定义的处理函数
外,还可以为 SIG_DFL
(采用缺省的处理方式)或 SIG_IGN
(忽略信号)。它的处理函数只
有一个参数,即信号值。
sa_mask
是一个信号集,它可以指定在信号处理程序执行过程中哪些信号应当被阻塞,
在调用信号捕获函数之前,该信号集要加入到信号的信号屏蔽字中。
sa_flags
中包含了许多标志位,是对信号进行处理的各个选择项。它的常见可选值如下:
选项 |
含义 |
SA_NODEFER/SA_NOMASK |
当捕捉到此信号时,在执行其信号捕捉函数时,系统不会自动阻塞此信号 |
SA_NOCLDSTOP |
进程忽略子进程产生的任何 SIGSTOP、SIGTSTP、SIGTTIN 和 SIGTTOU 信号 |
SA_RESTART |
可让重启的系统调用重新起作用 |
SA_ONESHOT/SA_RESETHAND |
自定义信号只执行一次,在执行完毕后恢复信号的系统默认动作 |
将 sigaction
结构体中的 sa_flags
成员赋值为 0,修改后的部分代码如下。
1 2 3 4 5 6 7 8 9 10 11 12
| while(1){ if(sigismember(&set,SIGINT)){ sigemptyset(&action1.sa_mask); action1.sa_handler=my_func; action1.sa_flags=0; sigaction(SIGINT,&action1,NULL); }else if(sigismember(&set,SIGQUIT)){ sigemptyset(&action2.sa_mask); action2.sa_handler = SIG_DFL; sigaction(SIGTERM,&action2,NULL); } }
|
这样修改后,程序确实正常运行了。但是根据该书所述和在网上查询,始终未能理解为何这样操作,而且之后尝试赋其他值,依然正常运行。网上国内的氛围就是博客间互相复制互相抄袭,找不到多少主观的分析,所以一直未能解决,仅在此做下记录。