sigaction函数的使用

简介: sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。 他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该使用这个接口) 给信号signum设置新的信号处理函数act, 同时保留该信号原有的信号处理函数...
sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。
他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该使用这个接口)
给信号signum设置新的信号处理函数act, 同时保留该信号原有的信号处理函数oldact
int sigaction(int signo,const struct sigaction *restrict act,
              struct sigaction *restrict oact);
结构sigaction定义如下:
struct sigaction{
  void (*sa_handler)(int);
   sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};
sa_handler字段包含一个信号捕捉函数的地址
sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。
sa_flag是一个选项,主要理解两个
SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启
SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针
最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他。
例子:
#include
#include
#include
 
void show_handler(int sig)
{
    printf("I got signal %d\n", sig);
    int i;
    for(i = 0; i < 5; i++) {
        printf("i = %d\n", i);
        sleep(1);
    }
}
 
int main(void)
{
    int i = 0;
    struct sigaction act, oldact;
    act.sa_handler = show_handler;
    sigaddset(&act.sa_mask, SIGQUIT); //见注(1)
    act.sa_flags = SA_RESETHAND | SA_NODEFER; //见注(2)
    //act.sa_flags = 0; //见注(3)
 
    sigaction(SIGINT, &act, &oldact);
    while(1) {
        sleep(1);
        printf("sleeping %d\n", i);
        i++;
    }
}
 
注:
(1)    如果在信号SIGINT(Ctrl + c)的信号处理函数show_handler执行过程中,本进程收到信号SIGQUIT(Crt+\),将阻塞该信号,直到show_handler执行结束才会处理信号SIGQUIT。
 
(2)    SA_NODEFER       一般情况下, 当信号处理函数运行时,内核将阻塞<该给定信号 -- SIGINT>。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号。 SA_NODEFER是这个标记的正式的POSIX名字(还有一个名字SA_NOMASK,为了软件的可移植性,一般不用这个名字)    
       SA_RESETHAND    当调用信号处理函数时,将信号的处理函数重置为缺省值。 SA_RESETHAND是这个标记的正式的POSIX名字(还有一个名字SA_ONESHOT,为了软件的可移植性,一般不用这个名字)   
 
(3)    如果不需要重置该给定信号的处理函数为缺省值;并且不需要阻塞该给定信号(无须设置sa_flags标志),那么必须将sa_flags清零,否则运行将会产生段错误。但是sa_flags清零后可能会造成信号丢失!
 

sigaction

 
  sigaction(查询或设置信号处理方式)
 
  相关函数 signal,sigprocmask,sigpending, sigsuspend, sigemptyset
 
  表头文件 #include
 
  定义函数 int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
 
  函数说明 sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
 
  如参数结构sigaction定义如下
 
  struct sigaction {
 
  union{
 
  __sighandler_t sa_handler;
 
  void (*_sa_sigaction)(int,struct siginfo *, void *);
 
  }_u
 
  sigset_t sa_mask;
 
  unsigned long sa_flags;
 
  void (*sa_restorer)(void);
 
  }
 
  信号处理函数可以采用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *, void *)。到底采用哪个要看sa_flags中是否设置了SA_SIGINFO位,如果设置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此时可以向处理函数发送附加信息;默认情况下采用void (*sa_handler)(int),此时只能向处理函数发送信号的数值。
 
  sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。
 
  sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁置。
 
  sa_restorer 此参数没有使用。
 
  sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。 
 
  sa_falgs还可以设置其他标志:
 
  SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
 
  ··SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
 
  SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号
 
  sigaction

sigaction()

示例

  #include
 
  static void int_hander(int s)
 
  {
 
  printf("Catch a signal sigint\n");
 
  }
 
  int
 
  main(void)
 
  {
 
  int i;
 
  struct sigaction act, oact;
 
  act. sa_handler = int_hander;
 
  sigemptyset(&act. sa_mask); //清空此信号集
 
  act. sa_flags = 0;
 
  sigaction(SIGINT, &act, &oact);
 
  //signal(SIGINT, SIG_IGN);
 
  while(1){
 
  for(i=0; i<5; i++){
 
  write(1, ".", 1);
 
  sleep(1);
 
  }
 
  write(1, "\n", 1);
 
  }
 
  sigaction(SIGINT, &oact, NULL); //恢复成原始状态
 
  return 0;
 
  }
目录
相关文章
|
传感器 监控 物联网
FastBond2阶段2——基于ESP32C3开发的简易IO调试设备
FastBond2阶段2——基于ESP32C3开发的简易IO调试设备
251 0
|
存储 缓存 虚拟化
PCIe地址转换服务(ATS)详解
PCIe地址转换服务(ATS)详解
3146 1
PCIe地址转换服务(ATS)详解
|
监控 安全 Unix
进程回收的实现方式与注意事项:Linux C/C中的回收机制
进程回收的实现方式与注意事项:Linux C/C中的回收机制
715 1
|
Linux 编译器 Shell
深入理解Linux中的动态库与静态库
深入理解Linux中的动态库与静态库
|
Java 开发者
Java一分钟之-JavaFX布局管理:GridPane, VBox, HBox
本文介绍了JavaFX的三种常用布局管理器:GridPane、VBox和HBox。GridPane用于创建二维网格布局,需设置行和列约束以防止控件重叠。VBox按垂直方向堆叠控件,记得设置间距。HBox水平排列控件,可能需要分配额外空间以避免水平滚动条。示例代码展示了这三种布局的使用。理解并运用这些布局管理器能提升JavaFX应用的界面设计。
596 0
|
11月前
|
Java 编译器 程序员
Java多态背后的秘密:动态绑定如何工作?
本文介绍了Java中多态的实现原理,通过动态绑定和虚拟方法表,使得父类引用可以调用子类的方法,增强了代码的灵活性和可维护性。文中通过具体示例详细解析了多态的工作机制。
226 4
|
Linux
使用backtrace打印程序crash堆栈
使用backtrace打印程序crash堆栈
296 0
|
数据可视化 数据管理 大数据
【开源项目】轻量元数据管理解决方案——Marquez
【开源项目】轻量元数据管理解决方案——Marquez
683 57
|
Ubuntu 架构师 Linux
内存泄露专题(5)动态内存追踪大杀器:bcc
内存泄露专题(5)动态内存追踪大杀器:bcc
387 0
|
负载均衡 Kubernetes 网络协议
kubernetes--kube-proxy组件深入理解
每台机器上都运行一个kube-proxy服务’它监听API server中service和endpoint的变化情 况,并通过iptables等来为服务配置负载均衡(仅支持TCP和UDP)
657 0