信号
7.1 信号的概念
什么是信号:
信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
信号的特点:
简单,不能携带大量信息,满足特定条件才会发生。信号也叫软中断,有可能会有延迟。
信号的实现机制:
信号实际上是由内核发送,内核来处理收到的信号。收到信号的进程,必须对信号做出处理(忽略,捕获,默认动作都行)
信号的产生:
信号状态:
产生 递达:信号被捕捉并处理 未决:信号被阻塞
信号四要素:
编号、事件、名称、默认处理动作
7.2 进程处理信号行为
1、默认动作
2、忽略
3、捕捉
(后面两种处理行为就需要涉及到信号集了)
7.3 信号集处理函数
(1)首先要了解什么是信号集:
信号集被定义为一种数据类型:
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t
//信号集用来描述信号的集合,每个信号占用一位(64位)。
//Linux所支持的所有信号可以全部或部分的出现在信号集中,主要与信号阻塞相关函数配合使用。
//下面是为信号集操作定义的相关函数:
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
(2)信号集处理函数:
那我们一个一个来看
int sigemptyset(sigset_t *set); //清空信号集嘛,传参传什么也应该很清楚了 初始化由set指定的信号集,信号集里面的所有信号被清空,相当于64为置0;
int sigfillset(sigset_t *set);//填满信号集嘛 调用该函数后,set指向的信号集中将包含linux支持的64种信号,相当于64为都置1;
int sigaddset(sigset_t *set, int signum);//添加信号进去 在set指向的信号集中加入signum信号,相当于将给定信号所对应的位置1;
int sigdelset(sigset_t *set, int signum);//删除信号出去 在set指向的信号集中删除signum信号,相当于将给定信号所对应的位置0;
int sigismember(const sigset_t *set, int signum);//看看是不是已经在里面了 判定信号signum是否在set指向的信号集中,相当于检查给定信号所对应的位是0还是1。
好,看完上面这些处理函数,其实这几个函数真的就是对信号集进行操作而已,而不会对具体信号有什么动作。 别急
7.4 阻塞信号集
阻塞信号集也叫做当前进程的信号屏蔽字。 这里的屏蔽应该理解为阻塞而非忽略
(1)sigprocmask 调用sigprocmask函数可以读取或更改进程的信号屏蔽字。
#include<signal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
//成功返回0,失败返回-1
参数释义: set:用于更改的信号集 oldset:用于传出原信号集 how:怎么操作set
how的参数选择: SIG_BLOCK:set包含了我们希望添加到当前信号屏蔽字的信号 SIG_UNBLOCK:set包含了我们希望从当前信号屏蔽字移除的信号 SIG_SETMASK:设置当前信号屏蔽字为set所指向的值。
这个要生效的话,至少需要有其中一个信号的驱动(就是哪个倒霉的过来阻塞一下)
(2)sigpending
#include<signal.h>
int sigpending(sigset_t *set);
//成功返回0,失败返回-1
功能:读取当前进程的未决信号集,通过set参数传出。
到这里差不多可以去弄信号集了
7.5 信号捕捉设定
防止信号意外死亡
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
参数释义 signum 捕捉的信号 act 传入的动作 oldact 原动作
我去借鉴了一段代码:捕捉我们给自己定时发送的14号自杀信号:
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/time.h>
//定义捕捉函数
void catch_sig(int num){
printf("catch %d sign", num);
}
int main(){
//注册捕捉函数
struct sigaction act;
//说明为你使用的是sigaction结构体中的第一个捕捉函数
act.sa_flags=0;
//那个捕捉函数的函数指针指向我们上面自己写的捕捉函数catch_sig
act.sa_handler=catch_sig;
//清空信号集
sigemptyset(&act.sa_mask);
sigaction(SIGALRM, &act, NULL);
//setitimer 5秒之后每隔3秒来一次信号
struct itimerval myit={{3,0},{5,0}}; //这个后续章节会提到,我现在也不是很清楚
setitimer(ITIMER_REAL, &myit, NULL);//还有这个
while(1){
printf("Who can kill me!n");
sleep(1);
}
return 0;
}
7.6 C标准库信号处理函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
//signum 要捕捉的信号
//handler 要执行的捕捉函数指针,函数应该声明 void func(int);//函数名可变
7.7 SIGCHLD 信号处理
17号信号
产生条件:
子进程结束时 子进程收到SIGSTOP信号时 子进程处在睡眠状态,收到SIGCONT信号唤醒时
哎,这个有点不好搞,我先把其他方法搞清楚咯 代码也是抄来的,贴这儿了
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
void catch_sig(int num){
pid_t pid=waitpid(-1, NULL, WNOHANG);
if(pid>0){
printf("wait child %d okn", pid);
}
}
int main(){
int i=0;
pid_t pid;
for(i=0; i<10; i++){
pid=fork();
if(pid==0){
break;
}
}
if(i==10){
//father
struct sigaction act;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
act.sa_handler=catch_sig;
sigaction(SIGCHLD, &act, NULL);
while(1){
sleep(1);
}
}else if(i<10){
printf("I am %d child, pid=%dn", i, getpid());
sleep(i);
}
return 0;
}
- Performance Schema使用简介(一)
- golang 垃圾回收 gc
- Go语言服务器开发之简易TCP客户端与服务端实现方法
- 移动搜索SEO分享:PHP自动生成百度开放适配及360移动适配专用的Sitemap文件
- 分享两种外链跳转方法,可避免权重流失。
- go语言十大排序算法总结
- 网站安全检测提示“页面异常导致本地路径泄漏”的解决办法
- Go语言归并排序算法实现
- 超強统计插件:My Visitors在知更鸟主题下的修改教程
- 让知更鸟主题的分类图标支持二级分类
- nwui —— 又一个go语言图形界面解决方案
- 分享博客统计中的动态运行天数代码
- GO语言标准错误处理机制error用法实例
- go的websocket实现原理与用法详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 树莓派基础实验31:MPU6050陀螺仪加速度传感器实验
- springboot gradle mybatis mysql配置(注解)
- PHP入门之流程控制
- 常用进制转换方法(取商留余)原理解析, 附基于栈实现进制转换的代码
- 用 jdom 解析 xml 文件时如何解决中文问题?如何解析?
- PHP入门之函数
- spring boot 启动报错 org/springframework/core/ErrorCoded
- PHP入门之数组
- PHP基础之排序
- 关于mysql limit offset的一点优化
- PHP基础之查找
- PHP木马免杀的一些总结
- PHP基础之面向对象篇
- PHP变量覆盖漏洞小结
- 算法复习 : 插入排序原理,记忆,时间复杂度 (7行java实现)