Linuxc/c++之信号基础

目录

1. 信号的本质

2. 信号的产生

3. 信号的处理过程

4. 信号的分类

5. 信号注册与信号发送

6. 信号屏蔽


1. 信号的本质

信号的本质就是整数,是用户模式下用来模拟硬件中断的一种方式。

硬件中断(真正中断):物理层面

软件中断(模拟中断):模拟

2. 信号的产生

  1.  硬件产生
  2.  内核产生
  3.  进程产生

3. 信号的处理过程

如果当前进程A正在运行,然后内核,硬件或者其它进程发送信号给进程A

进程A接收到信号之后:

1. 直接做信号本身规定的对应处理(例如SIGINT就是关闭进程(ctrl + C))

2. 做事先注册好的信号处理(信号注册函数signal(信号,处理函数))

3. 信号被屏蔽,等待信号屏蔽解除然后做出相应处理

4. 信号的分类

4.1 Linux提供的64个信号

kill -l

4.2 按照可靠性分类

不可靠信号:非实时性的信号  由UNIX提供的       1  --- 31

可靠信号:实时性的信号   后来扩充的                 32 --- 64

4.3 按照类型分

标准信号:操作系统提供的信号

自定义信号:用户自定义的信号    SIG_USR

5. 信号注册与信号发送

        5.1 信号注册

                5.1.1 signal函数

                不含signal 函数的一个进程,      使用Ctrl  +  C 或者  Ctrl   + \  可以结束当前进程

                标准信号处理函数

                typedef void (*sighandler_t)(int);

                sighandler_t signal(int signum,sighandler_t handler);

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int main(){

	printf("pid: %d\n",getpid());

	int n = 0;
	while(1){
		printf(">> %d\n",n++);
		sleep(1);
	}

	return 0;
}

 

         使用signal函数注册SIGINT信号后, 当注册SIGINT信号之后, 使用Ctrl + C 发送SIGINT信号就会调用自定义的信号处理函数

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

//SIGINT信号处理函数
void hand(int val){
	printf("val---%d\t想干掉我,没门!\n",val);   //val 为 signum  SIGINT的值为2
}

int main(){

	signal(SIGINT,hand); //注册信号处理(信号自己处理,不交给操作系统处理)
	printf("pid: %d\n",getpid());

	int n = 0;
	while(1){
		printf(">> %d\n",n++);
		sleep(1);
	}

	return 0;
}

 

                5.1.2 sigaction函数(高级信号注册函数)

                        sigaction()高级信号注册函数对应sigqueue()高级信号发送函数

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

                        参数一: 信号的id(例如SIGINT信号的signum 为 2)

                        参数二: 新的信号处理方式

                        参数三: 旧的信号处理方式

                        struct sigaction{

                                void (*sa_handler)(int);    //原来的信号处理函数

                                void (*sa_sigaction)(int, siginfo_t *,void *);  //高级的信号处理函数

                                sigset_t   sa_mask;     //信号屏蔽

                                int  sa_flags;                //使用原来的还是高级的信号处理函数

                                void (*sa_restorer)(void);   //目前未使用

                        };

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void hand(int n){
	printf("基本的信号处理函数!\n");
}
//参数1 信号   参数2 信号的一些信息(信号发送者给传入的数据)    参数3 注册信号传入的参数
void handler(int n,siginfo_t* siginfo,void* arg){
	printf("高级的信号处理函数!\n");
	printf("n:%d,msg:%d\n",n,siginfo->si_int);
}
int main(){
	printf("pid--->%d\n",getpid());
	struct sigaction act = {0};
	struct sigaction oldAct = {0};

	act.sa_handler = hand;      //信号处理函数
	act.sa_sigaction = handler;  //高级信号处理函数
	//sa_mask                    //信号屏蔽
	//*sa_restorer               //目前未使用
	act.sa_flags = SA_SIGINFO;  //sigaction替换handler

	//SIGINT
	sigaction(2,&act,&oldAct);  //注册高级信号处理
	//参数三作为返回值存在的

	int n = 0;
	while(1){
		printf(">>> %d\n",n++);
		sleep(1);
	}

	return 0;
}

        5.2 信号发送

                5.2.1 kill函数

                        kill(pid,sid);    参数1: 进程id  参数二: 信号  

#include <stdio.h>
#include <unistd.h>
//信号的发送之kill函数
int aton(char* str){
	int num = 0;
	while(*str){
		num = num * 10 + (*str-'0');
		str++;
	}
	return num;
}

int main(int argc,char* argv[]){
	int pid = aton(argv[1]);   //进程id
	int sid = aton(argv[2]);   //信号id  2(SIGINT信号) 
	printf("%d %d",pid,sid);

//       进程id  信号id
	kill(pid,sid);
	return 0;
}

 

                5.2.2 sigqueue函数(高级信号发送函数)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

int aton(char* str){
	int num = 0;
	while(*str){
		num = num * 10 + (*str-'0');
		str++;
	}

	return num;
}
int main(int argc,char* argv[]){
	int pid = aton(argv[1]);
	int sid = aton(argv[2]);

	union sigval u;
	u.sival_int = 6666666;

	sigqueue(pid,sid,u);

	return 0;
}

 

                5.2.3 kill命令

                        kill   sid   -s   pid

                                sid:  信号id       pid:  进程id

                         

6. 信号屏蔽

        int sigprocmask(int how, const sigset_t* set, sigset_t* oldset);

        参数一: 是否屏蔽(或者其它的操作)  SIG_BLOCK(屏蔽)  SIG_UNBLOCK(不屏蔽)

        参数二: 指向信号集的指针,新设的信号集

        参数三: 指向信号集的指针,原来的信号集

        返回值: 成功返回 0

        

        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); //判断某个信号是否在信号集中

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void hand(int n){
	printf("基本的信号处理函数!\n");
}
int main(){
	printf("pid: %d\n",getpid());
	sigset_t set,oldSet;
	sigemptyset(&set);     //清空信号集

	sigaddset(&set,2);
	//5秒钟不设置信号屏蔽
	signal(2,hand);
	sleep(5);
	//设置信号屏蔽20秒
	//sigismember  判断信号是否在信号集中
	int ret;
	if(1 == sigismember(&set,2)){
		printf("设置信号屏蔽!\n");
		ret = sigprocmask(SIG_BLOCK,&set,&oldSet);
		//参数1 屏蔽还是解除屏蔽
		//参数3为返回值  返回old信号集
		if(0 == ret) 
			printf("设置信号屏蔽成功!\n");
		else
			printf("设置信号屏蔽失败!\n");
	}
	sleep(20);
	//解除信号屏蔽
	if(1 == sigismember(&set,2)){
		printf("解除信号屏蔽!\n");
		ret = sigprocmask(SIG_UNBLOCK,&set,&oldSet);
		if(0 == ret) 
			printf("解除信号屏蔽成功!\n");
		else
			printf("解除信号屏蔽失败!\n");
	}
	while(1);

	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

石小浪♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值