一 函数介绍
Linux/Unix中的sigaction函数运行调用程序检查或指定与特定信号相关的动作。
- 参数sig用于指定动作的信号编号;
- 参数act是一个指向struct sigaction结构的指针,用于指定要采取的动作,如果act为NULL,对sigaction的调用就不会改变与信号;
- 参数oact是一个指向struct sigaction结构的指针,用于接收与信号相关的前一个动作相关的动作。 如果oact为NULL,对sigaction的调用就不会返回与信号相关的前一个动作。
#include <signal.h>
int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);
// 如果成功调用则返回0,如果失败则返回-1,并设置errno
二 注意事项
note 1 : 其中struct sigaction的sa_handle成员有两个特殊值: SIG_DFL 和 SIG_IGN。 SIG_DFL值指定sigaction应该恢复信号的默认行为。SIG_IGN值指定进程应该忽略它们(或丢弃)。
note 2 : POSIX中保证write是异步信好的,也就是说,可以从一个信号处理函数内部安全地调用它。fprintf或strlen函数没有类似的按保证,但在某些实现中它们可能是异步信号安全的。
note 3 : 只有当信号处理函数和main程序都使用perror和printf时,信号安全才会成为问题。而在下面的代码中只有main函数使用了perror和printf,因此不会造成信号安全问题。
note 4 : 代码中的doneflag是一个临界区,因为信号处理函数可以在main程序检查这个变量时修改它。在这里,通过将doneflag声明为sig_atomic_t来处理这个问题。sig_atomic_t是一个小到足以进行原子访问的整数类型。dongflag的限定符volatile通知编译器该变量的修改可能与程序的执行是异步的。否则,编译器可能会假设doneflag在while循环中没有被修改,进而生成旨在循环的第一次迭代中对条件进行检测的代码。
note 5: 当信号处理函数和main程序都需要访问大于sig_atomic_t的数据时,一定要非常小心,以确保程序的一部分不会修改另一部分正在读取的数据
三 代码实现
/* 该程序用来计算随机选取值的正弦平均值,来估算0~1这个区间内sin(x)的平均值
* main程序中的循环在0~1之间选择一个随机值x,将sin(x)的值添加到一个不断变化的总和中,将计数值加1,并打印当前的计数值和平均值
* 程序说明了如何用信号处理函数优雅地终止一个程序。
* 用户在标准输入中输入Ctrl-C时,信号处理函数就会设置doneflag来说明程序应该终止。
* 在计算循环的每次迭代中,程序都会检测doneflag,判断是否应该退出循环并打印最后一条消息。
* */