Linux内核编程 信号signal、sigaction使用案例

目录

一:无参信号和带参信号

二:sigaction信号绑定

三:sigqueue发送信号

四:带参信号


一:无参信号和带参信号

信号处理的两种方案:无参信号和带参信号

信号是IPC技术其中的一种,IPC的目的是因为进程本身不能实现数据的交互(共享数据),所以通过IPC来进行数据的传递

一个进程执行完某一个过程后向另外一个进程发送信号,使得另外的一个进程中断当前的所有的逻辑去执行信号的操作

相当于一个进程(父进程)可以去操控另一个进程(子进程)【通过一个信号达到一个间接的操控】

可以通过父进程通过发送不同的信号,去执行不同的事情,达到这样一种间接的控制

                           无参           有参

信号绑定            signal    sigaction

信号发送             kill        sigqueue

对于signal信号绑定函数   无法实现数据传递

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

using namespace std;

//信号处理函数
void signal_function(int num)
{
	cout << "signal_function 被触发 pid = " << getpid() << "num = "<<num<< endl;
	//if (num == 10)
	//{
	//	//num  10  做一件事情
	//}
	//else if (num == 12)
	//{
	//	//num  12  做另外一件事情
	//}

	//switch (num)
	//{
	//case 10:  //num  10  做一件事情
	//	break;
	//case 12:  //num  12  做另外一件事情
	//	break;
	//default:
	//	break;
	//}

}

int main()
{
	pid_t pid = 0;
	//信号绑定
	signal(SIGUSR1, signal_function);//num--10
	signal(SIGUSR2, signal_function);//num--12

	pid = fork();
	if (pid > 0)
	{
		sleep(5);
		for (int i = 0; i < 3; i++)
		{
			//父进程给子进程发送信号
			kill(pid, SIGUSR1);
			//sleep(1);
		}

		while (1)
		{
		}
	}
	else if (pid == 0)
	{
		while (1)
		{
			cout << "子进程 pid = " << getpid() << endl;
			sleep(1);
		}
	}
	return 0;
}

要想实现数据传递,需要学习另外一种信号绑定的写法   sigaction

二:sigaction信号绑定

包含头文件<signal.h>

功能:sigaction函数用于改变进程接收到特定信号后的行为

原型

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

参数

该函数的第一个参数为信号的值,可以为除sigkill及sigstop外的任何一 个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)

第二个参数是指向结构sigaction的一个实例的指针,在结构 sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理

第三个参数oldact指向的对象用来保存原来对相应信号 的处理,可指定oldact为null

返回值:函数成功返回0,失败返回-1

参数:    第一个参数signum :信号ID  

               第三个参数oldact放空NULL

               第二个参数是指向sigaction的结构体指针

从中看出结构体中属性1 2 5函数  都是函数指针

属性1类似之前学习的   void signal_function(int num):没有带参数传递的函数指针【无参信号,不能数据传递

sigaction的操作有两种,一种是带参,一种是不带参,

不带参的写法和void signal_function(int num)差不多,

因此可以看出

图中的结构体中有一个函数指针   void  (*sa_handler)(int);就是专门处理不带参的信号

从这个结构体中主要还是需要学习一下带参,也就是

属性2:void  (*sa_sigaction)(int, siginfo_t *, void *);【有参信号,可以实现数据传递

结构体中按道理来说不可以包含函数,但是可以包含函数指针 ,因为函数指针最终还是可以识别为指针变量

sigaction兼容了signal写法,从上图中的结构体的属性中不难看出,sigaction属性1是不带参信号写法,属性2是带参信号的写法

结构体属性中的flag就是一个参数说明,说明当前是带参还是不带参

(因为sigaction结构体属性包含两种 无参和带参)

三:sigqueue发送信号

功能:

新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用

原型:

int sigqueue(pid_t pid, int sig, const union sigval value);

参数

sigqueue的第一个参数是指定接收信号的进程id,

                    第二个参数确定即将发送的信号,

                    第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值

返回值

成功返回0,失败返回-1

查看使用手册说明 

int sigqueue(pid_t pid, int sig, const union sigval value);

第一 二个参数:pid sig 给哪个进程 发送什么信号

第三个参数 value就是数据相关  union联合体有点类似于结构体

其中的联合体原型

有一个int和一个void*类型的数据,数据传递可以是一个简单的int数据,也可以是无类型指针(这个无类型指针可以指向任何数据,但是没有void*的函数数据处理,信号使用的人很少就没有特意开发这个函数处理,但是这个void*是保留下来的,如果以后的版本更新之后就会有了;但目前ubuntu20.04的版本这个void*还不可使用)

四:带参信号

带参信号的绑定:sigaction

带参信号的发送:sigqueue

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

using namespace std;

//参数void*是预留的,具体目前ubuntu20.04还没有开发出来
void sigaction_function(int num, siginfo_t* pinfo, void* pvo)
{
	int res = pinfo->si_int;
	cout << "sigaction_function 接收到的数据 res = " << res << endl;
}

int main()
{
	pid_t pid = 0;

	//定义结构体
	struct sigaction act;
	act.sa_sigaction = sigaction_function;//给结构体属性中的函数指针赋值
	act.sa_flags = SA_SIGINFO;//表示设置为带参的信号

	//带参的信号绑定
	//参数1 信号ID 参数2 结构体指针 参数3 NULL
	sigaction(SIGUSR1, &act, NULL);

	pid = fork();

	if (pid > 0)
	{
		sleep(5);
		//准备value union联合体类似结构体
		union sigval value;
		value.sival_int = 123456;

		//sigqueue发送信号
		sigqueue(pid, SIGUSR1, value);
		while (1)
		{
		}
	}
	else if (pid == 0)
	{
		while (1)
		{
			cout << "子进程 pid = " << getpid() << endl;
			sleep(1);
		}
	}
	return 0;
}

测试结果:

5000ms后,成功接收到数据

虽然真的可以传递int类型数据,但是用武之地太小了,因为真正传递数据不可能只传递一个int,还会传一些比如说结构体,比如说容器,数组等数据

这个也是信号经常被人诟病的问题之一

Qt中的信号和槽,是可以自定义信号,自己去写自己想要传输的数据,但是Qt就是借助这个Linux内核编程中的信号来形成的信号和槽的机制,只不过Qt自己升级了,提高其传递数据的功能能力

通过信号来传递数据  带参信号  Linux内核编程信号特性之一,虽然比较鸡肋,但是也是需要学习一下的

利用sigaction也可以写不带参的信号,如下写法

不带参信号和带参信号可以对比学习,

重要的部分:

无参信号:signal绑定信号         kill发送信号                不可数据传递

带参信号:sigaction绑定信号    sigqueue发送信号     可以数据传递(少量数据)

本节主要介绍的是带参的信号,不带参的信号学习如下:

不带参信号的学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chenruhan_QAQ_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值