一、函数原型:sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

signum参数指出要捕获的信号类型,act参数指定新的信号处理方式,oldact参数输出先前信号的处理方式(如果不为NULL的话)。

二、 struct sigaction结构体介绍

struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);
}
  • sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数
  • sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号集搁置
  • sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。
  • SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
  • SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
  • SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>int main()
{struct sigaction newact,oldact;/* 设置信号忽略 */newact.sa_handler = SIG_IGN; //这个地方也可以是函数sigemptyset(&newact.sa_mask);newact.sa_flags = 0;int count = 0;pid_t pid = 0;sigaction(SIGINT,&newact,&oldact);//原来的备份到oldact里面pid = fork();if(pid == 0){while(1){printf("I'm child gaga.......\n");sleep(1);}return 0;}while(1){if(count++ > 3){sigaction(SIGINT,&oldact,NULL);  //备份回来printf("pid = %d\n",pid);kill(pid,SIGKILL); //父进程发信号,来杀死子进程}printf("I am father .......... hahaha\n");sleep(1);}return 0;
}

结果:

/************************************************************************************************************************************************/

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 函数:
 signal 函数的使用方法简单,但并不属于 POSIX 标准,在各类 UNIX 平台上的实现不尽相同,因此其用途受

到了一定的限制。而 POSIX 标准定义的信号处理接口是 sigaction 函数,其接口头文件及原型如下:
 #include <signal.h>
 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

◆ signum:要操作的信号。
 ◆ act:要设置的对信号的新处理方式。
 ◆ oldact:原来对信号的处理方式。
 ◆ 返回值:0 表示成功,-1 表示有错误发生。

struct sigaction 类型用来描述对信号的处理,定义如下:

 struct sigaction{void     (*sa_handler)(int);void     (*sa_sigaction)(int, siginfo_t *, void *);sigset_t  sa_mask;int       sa_flags;void     (*sa_restorer)(void);};

在这个结构体中,成员 sa_handler 是一个函数指针,其含义与 signal 函数中的信号处理函数类似。成员

sa_sigaction 则是另一个信号处理函数,它有三个参数,可以获得关于信号的更详细的信息。当 sa_flags 成员的值

包含了 SA_SIGINFO 标志时,系统将使用 sa_sigaction 函数作为信号处理函数,否则使用 sa_handler 作为信号处理

函数。在某些系统中,成员 sa_handler 与 sa_sigaction 被放在联合体中,因此使用时不要同时设置。
 sa_mask 成员用来指定在信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会被

自动放入进程的信号掩码,因此在信号处理函数执行期间这个信号不会再度发生。
 sa_flags 成员用于指定信号处理的行为,它可以是一下值的“按位或”组合。
 
 ◆ SA_RESTART:使被信号打断的系统调用自动重新发起。
 ◆ SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
 ◆ SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
 ◆ SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
 ◆ SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
 ◆ SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。

re_restorer 成员则是一个已经废弃的数据域,不要使用。

下面用一个例程来说明 sigaction 函数的使用,代码如下

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>static void sig_usr(int signum)
{if(signum == SIGUSR1){printf("SIGUSR1 received\n");}else if(signum == SIGUSR2){printf("SIGUSR2 received\n");}else{printf("signal %d received\n", signum);}
}int main(void)
{char buf[512];int  n;struct sigaction sa_usr;sa_usr.sa_flags = 0;sa_usr.sa_handler = sig_usr;   //信号处理函数sigaction(SIGUSR1, &sa_usr, NULL);sigaction(SIGUSR2, &sa_usr, NULL);printf("My PID is %d\n", getpid());while(1){if((n = read(STDIN_FILENO, buf, 511)) == -1){if(errno == EINTR){printf("read is interrupted by signal\n");}}else{buf[n] = '\0';printf("%d bytes read: %s\n", n, buf);}}return 0;
}

在这个例程中使用 sigaction 函数为 SIGUSR1 和 SIGUSR2 信号注册了处理函数,然后从标准输入读入字符。程序运行后首先输出自己的 PID,如:My PID is 5904 
 这时如果从另外一个终端向进程发送 SIGUSR1 或 SIGUSR2 信号,用类似如下的命令:kill -USR1 5904

则程序将继续输出如下内容:
 SIGUSR1 received
 read is interrupted by signal
 
 这说明用 sigaction 注册信号处理函数时,不会自动重新发起被信号打断的系统调用。如果需要自动重新发起,则要设置 SA_RESTART 标志,比如在上述例程中可以进行类似一下的设置:sa_usr.sa_flags = SA_RESTART;

linux中sigaction函数详解相关推荐

  1. linux 中 sigaction 函数详解

    linux 中 sigaction 函数详解 一.函数原型 sigaction 函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作) int sigaction(int signum, ...

  2. Linux中fork()函数详解

    Linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  3. Linux中execl函数详解与日常应用(附图解与代码实现)

    目录 execl函数 exec函数族的日常应用 1.Linux中第一个终端的创建 2.终端下.c文件的执行 exec其实并不是一个函数,而是由六个以exec开头的函数所构成的一个函数族,如下图所示 e ...

  4. linux中 fopen函数,详解C语言中的fopen()函数和fdopen()函数

    C语言fopen()函数:打开一个文件并返回文件指针头文件: #include fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * ...

  5. linux中fork函数详解,fork() 函数详解

    fork() 函数是 linux/unix 下一种特别的创建子进程的函数,它不同与 Windows,这个函数在执行成功后会有两个返回值,一个返回值==0代表创建了子进程,一个返回值大于0代表还是当前程 ...

  6. Linux中fork函数详解

     一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不 ...

  7. Linux中ftok函数详解

    在ipc通信中 system V 模式的ipc通信中都需要一个key值来生成对应的ID,那么key是如何生成的呢? 通过函数ftok生成 #include <sys/types.h>#in ...

  8. linux中open函数详解

    1.open函数 包含头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> ope ...

  9. linux中write函数详解

    1.write函数 头文件#include <unistd.h> 三个参数 函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内. 返回值:如果顺利w ...

最新文章

  1. 大龄码农经验那么丰富,为什么很多公司都不招?
  2. 模拟linux文件系统的设计及实现_Linux后台服务器开发中,内存池设计与实现(c/c++)...
  3. Windows常用快捷键整理
  4. 你们期待的小屏旗舰来了: 骁龙855 没有刘海!
  5. linux 监控软件介绍,Linux中系统整体性能监控工具详细介绍
  6. Excel单元格自定义格式的一些基础知识
  7. 对称密钥和非对称密钥有什么区别,区别在哪里
  8. 什么是软件验收测试?验收测试的标准和流程介绍
  9. some website
  10. Linux下查找结构体定义的位置
  11. 用python实现水纹特效
  12. Nginx(二)配置虚拟主机
  13. 近年来计算机的就业情况图表,巧用Excel函数实现动态图表的制作
  14. STM32开发板搭建开发环境之安装篇
  15. 计算机学院优秀主讲教师评选细则,湖北中医药大学优秀主讲教师评选办法
  16. php watcher,vue 中的 watcher详解
  17. 福建师范大学 “挑战杯”校赛金银奖分析文档
  18. tx2 安装opencv4.1.1及opencv_contrib-4.1.1
  19. 最长公共前后缀(KMP中next数组求法)
  20. 微信多群直播机器人平台(一起学堂)

热门文章

  1. js获取日期周数,并根据周数算出当前周的开始和结束日期(周日开始,周六结束)
  2. 用matlab实现2fsk,基于MATLAB的2FSK的课程设计
  3. Typecho发布静态html,Typecho生成首页静态HTML密码版
  4. 云​大数据和计算技术周报(第45期) - 云+社区 - 腾讯云
  5. 分析全球最大美食点评网站万家餐厅数据 寻找餐厅经营成功的秘密
  6. Dubbo原理和使用
  7. 计算机教育杂志有核心期刊吗,计算机光盘软件与应用期刊_计算机科学与技术专业必修课_计算机科学与技术专业的好处...
  8. MYSQL卸载方法与安装方法
  9. Linux系统了解 Samba服务器配置的工作流程
  10. 海宝等离子服务器进不了系统,海宝等离子电源机用切割维修常见故障及处理方法...