signal和sigaction 分析
1:signal 函数
原型: sighandler_t signal(int signum, sighandler_t handler) typedef void (*sighandler_t)(int);
描述:signal函数用来在进程中指定当一个信号到达进程后该做什么处理,主要的两种方式有忽略某些信号,(监听到SIGTERM/SIGINT)退出前的打扫工作。信号处理函数的handler有两个默认值,分别是SIG_IGN和SIG_DFL,表示忽略和默认行为。而且signal函数是阻塞的,比如当进程正在执行SIGUSR1信号的处理函数,此时又来一个SIGUSR1信号,signal会等到当前信号处理函数处理完后才继续处理后来的SIGUSR1,不管后来的多少个SIGUSR1信号,统一看做一个来处理。还有SIGKILL和SIGSTOP这两个信号是signal函数捕捉不到的。
注意:signal函数的行为与linux的版本有关(因为signal属于系统调用),所以移植性不好,可用sigaction函数来替代(sigaction是标准POSIX函数),而且sigaction还扩展了signal函数的功能。
2:sigaction函数
原型:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
参数:
signum:信号值
act:信号的处理参数
oldact:保存信号上次安装时的处理参数(备份的作用)
返回值:0(success),-1(error)
struct sigaction {
void (*sa_handler)(int); //信号处理函数
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //信号屏蔽集
int sa_flags;
void (*sa_restorer)(void);// 已废弃
};
要点:
信号阻塞:同signal函数类似,当正处于某个信号的处理函数中时,这个信号再次到达会被阻塞,待信号处理函数完成之后再处理。
sa_mask :信号屏蔽集,所谓屏蔽并不是忽略,屏蔽的时间段是在信号处理函数执行期间,一旦处理函数执行完毕将会重新唤醒此信号。
sa_flags :SA_RESTART:表示如果一个信号到来时进程正在执行某个系统调用(read/write等),执行完信号处理函数后返回系统调用,此系统调用会重新调用而不会出错。
实例1(sa_mask的使用):
#include <errno.h>
#include <string.h> static void signal_handler(int sig)
{
printf("Got SIGUSR1\n");
printf("Processing SIGUSR1...\n");
sleep();
printf("sleep over\n");
} int main(int argc, char** argv)
{
char buf[];
int n = ;
printf("PID:%d\n", getpid());
struct sigaction act, oldact;
act.sa_handler = signal_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT);//把SIGINT信号加入屏蔽集
//act.sa_flags = SA_RESTART;
if(sigaction(SIGUSR1, &act, &oldact) < )
{
perror("sigaction error");
return -;
}
/*
for(;;){
memset(buf, 0, 20);
if((n = read(0, buf, 20)) < 0){
perror("read:");
}
else{
buf[n] = '\0';
printf("%d type got, string:%s\n", n, buf);
}
}
*/
sleep();
return ;
}
结果:

实例2(sa_flags=SA_RESTART):
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h> static void signal_handler(int sig)
{
printf("Got SIGUSR1\n");
printf("Processing SIGUSR1...\n");
sleep();
printf("sleep over\n");
} int main(int argc, char** argv)
{
char buf[];
int n = ;
printf("PID:%d\n", getpid());
struct sigaction act, oldact;
act.sa_handler = signal_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT);
act.sa_flags = SA_RESTART;//设置SA_RESTART flag
if(sigaction(SIGUSR1, &act, &oldact) < )
{
perror("sigaction error");
return -;
} memset(buf, , );
if((n = read(STDIN_FILENO, buf, )) < ){//行缓冲阻塞
perror("read:");
}
else{
buf[n] = '\0';
printf("%d type got, string:%s\n", n, buf);
} return ;
}
结果:

将 act.sa_flags = SA_RESTART; 这行代码屏蔽之后:

可以看到,SA_RESTART参数确实保证了被中断的系统调用在中断之后恢复之前的状态继续执行(系统调用中断出错应该报告Interrupted system call,不知我这里为何是core dumped?)。
signal和sigaction 分析的更多相关文章
- Linux 信号:signal 与 sigaction
0.Linux下查看支持的信号列表: france@Ubuntux64:~$ kill -l ) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP ) SIGA ...
- Linux进程间通信(一): 信号 signal()、sigaction()
一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...
- signal() 和 sigaction()
[摘自<Linux/Unix系统编程手册>] Unix系统提供了两种方式来改变信号处置:signal() 和 sigaction(). signal() 的行为在不同Unix实现间存在差异 ...
- 信号处理signal、sigaction、pause、信号嵌套处理、不可重入函数
信号的捕捉和处理 主要由signal和sigaction函数来完成.还有一个函数pause,它可用来响应任何信号,不过不做任何处理. 1.signal函数 typedef void (*sighand ...
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
signal函数 signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...
- linux c 之signal 和sigaction区别
http://blog.csdn.net/muge0913/article/details/7331129 要对一个信号进行处理,就需要给出此信号发生时系统所调用的处理函数.可以对一个特定的信号(除去 ...
- linux 信号signal和sigaction理解
今天看到unp时发现之前对signal到理解实在浅显,今天拿来单独学习讨论下. signal,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
- Linux信号(signal) 机制分析
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
- Linux信号(signal) 机制分析(转)
[摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核对于信号的处理流程包括信号的触发/注册/执 ...
随机推荐
- 当Kubernets遇上阿里云 -之七层负载均衡(一).
我们知道Kubernetes的service只能实现基于4层的负载均衡,无法提供7层之上的许多特性,诸如基于URL的负载均衡,SSL支持,三方授权等等:Ingress可以实现七层负载均衡的许多功能,唯 ...
- 20181016-4 Alpha阶段第1周/共2周 Scrum立会报告+燃尽图 03
此作业链接地址见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2248 Scrum master:王硕 一.小组介绍 组长:王一可 组员 ...
- 欢迎来怼---作业要求 20171015 beta冲刺贡献分分配规则
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 基础分 每人占个人总分的百分之40% leangoo里面的得分 每人占个人总分里 ...
- 2018软工实践—Alpha冲刺(8)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 多次测试软件运行 学习OPENMP ...
- rsa加密算法,前后端实现。
前端js: 下载地址:http://travistidwell.com/jsencrypt/ js第一版本: // 对数据加密 function encrypt(enStr){ //没有加载jsenc ...
- alpha8/10
队名:Boy Next Door 燃尽图 晗(组长) 今日完成 和队友讨论alpha版的最终界面. 明日工作 确定alpha版既定功能的正常使用. 还剩下哪些任务 账号绑定功能以及账单信息的下载. 困 ...
- lintcode-397-最长上升连续子序列
397-最长上升连续子序列 给定一个整数数组(下标从 0 到 n-1, n 表示整个数组的规模),请找出该数组中的最长上升连续子序列.(最长上升连续子序列可以定义为从右到左或从左到右的序列.) 注意事 ...
- vue-cli脚手架搭建
我们使用vue-cli来搭建整个项目,vue-cli就是一个脚手架,步骤很简单,输入几个命令之后就会生成整个项目,里面包括了webpack.ESLint.babel很多配置等等,省了很多事 Vue+ ...
- laravel连接多个不同数据库的单例类
在連接多個不同數據庫時,需要寫多個連接,爲了簡化該操作,可以使用該基類,不同的數據庫只要建立好相對應的類繼承該類,就可以使用ORM模型進行操作了. class singletonInstance { ...
- javascript之容易出错的地方
1: 不是所有的非空对象都有toString()方法的 var obj = Object.create(null); console.log(obj.toString()); // false; ...