信号

举报
看,未来 发表于 2020/12/29 23:14:48 2020/12/29
【摘要】 目录 7.1 信号的概念 7.2 进程处理信号行为 7.3 信号集处理函数 7.4 阻塞信号集 7.5 信号捕捉设定 7.6 C标准库信号处理函数 7.7 SIGCHLD信号处理 7.1 信号的概念 什么是信号: 信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。 信号的特点: 简单,不能...

目录

7.1 信号的概念

7.2 进程处理信号行为

7.3 信号集处理函数

7.4 阻塞信号集

7.5 信号捕捉设定

7.6 C标准库信号处理函数

7.7 SIGCHLD信号处理




7.1 信号的概念

什么是信号:

信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。

信号的特点:

简单,不能携带大量信息,满足特定条件才会发生。信号也叫软中断,有可能会有延迟。

信号的实现机制:

信号实际上是由内核发送,内核来处理收到的信号。收到信号的进程,必须对信号做出处理(忽略,捕获,默认动作都行)

信号的产生:

这里是引用

信号状态:

产生
递达:信号被捕捉并处理
未决:信号被阻塞

信号四要素:

编号、事件、名称、默认处理动作

7.2 进程处理信号行为
1、默认动作
2、忽略
3、捕捉
(后面两种处理行为就需要涉及到信号集了)

  
 
  • 1
  • 2
  • 3
  • 4
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)
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

(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

  
 
  • 1
  • 2
  • 3
  • 4

参数释义:
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


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

功能:读取当前进程的未决信号集,通过set参数传出。

到这里差不多可以去弄信号集了

7.5 信号捕捉设定

防止信号意外死亡
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);


  
 
  • 1
  • 2

参数释义

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 sig\n", 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;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
7.6 C标准库信号处理函数

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

//signum 要捕捉的信号
//handler 要执行的捕捉函数指针,函数应该声明 void func(int);//函数名可变


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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 ok\n", 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=%d\n", i, getpid());
		sleep(i);
	}
	return 0;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

文章来源: lion-wu.blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。

原文链接:lion-wu.blog.csdn.net/article/details/103946100

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。