进程间通信(信号)

本文详细介绍了Linux系统中信号处理的基本概念和技术,包括信号的作用、如何使用signal函数注册信号处理函数,以及信号集的管理和使用。此外,还探讨了SIGALRM信号的定时触发机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux系统进程间通信有很多种方式:较多使用的有信号,管道以及System VIPC。各种通信方式各有优缺点。这部分主要就进程间通信方式进行总结。

1 信号。

信号进行进程间通信方式有一点需要明确:信号只能通知,不能在进程间共享数据资源。也就是说信号仅仅是告诉你一下某个事情发生了。而我们的程序则可以对这个信号进行各种我们自定义或者默认的处理,更或者当做没有听见。

那么既然是通知一件事情发生了,那肯定是我们关心的一些事情。计算机不像我们人类,告诉我们事情不能任意的表达,所以告诉我们的事情都有固定的格式。那么我们系统可以告诉我们哪些事情呢?我们可以通过kill -l在系统中查看。


这是我的系统输出 Ubuntu系统内核为4.4.0。目前该系统定义的有64种信号。在编写程序的时候这些信号被定义为整型(正整型)常量并放在<signal.h>头文件中。

从该图中可以看出不存在0信号,该信号在POSIX定义为空信号,系统有特殊的应用

并不是所有主机显示的信号都一样,不同的操作系统对信号的定义是不一样的

上面的信号这里不一一介绍说明,会在后期的学习和编码用例中分别举例说明。


到这里的时候可能会考虑一个问题,信号的种类知道了,那么系统怎么通知我呢?

我们使用signal函数(该函数的定义可以使用man查询)定义我们感兴趣的信号,并对该信号执行我们的处理方式。一般情况下对信号的处理有三种方式SIG_IGN(忽略信号不做任何处理)、SIG_DEF(执行系统自定义的默认操作)、自定义我们的操作函数。下面使用一段代码来看看signal的处理方式。

#include
#include
#include
#include
void sighand(int num)
{
	printf("The signum:%d\n",num);
	printf("自定义信号处理\n");
}


int main(int argc,char **argv)
{
	
	//signal(SIGINT,SIG_DFL);
	//signal(SIGINT,SIG_IGN);
	signal(SIGINT,sighand);

	while(1)
	{
		pause();
	}
}

使用:signal(SIGINT,SIG_DFL);按下ctrl+c之后将会执行系统默认的操作终止程序;调用signal(SIGINT,SIG_IGN);则会忽略信号系统没有任何影响;执行signal(SIGINT,sighand);则会执行自定义的函数输出字符串和信号编号。

不过需要注意一点有两个信号不能忽略:SIGKILL和SIGSTOP

上面的信号都是系统发送到我们的应用程序的,但是是否可以进程向进程发送信号呢?当然设计者早就想到了这层,使用kill函数,就能达到这样的目的。下面这段代码子进程在5秒后向父进程发送SIGINT信号。(kill不但将信号发给进程还发给该进程组)

#include
#include
#include
#include
void sighand(int num)
{
	printf("收到子进程发来的信号:%d\n",num);
}
int main()
{
	pid_t pid;
	pid_t fad=getpid();
	signal(SIGINT,sighand);
	if((pid==fork())==0)
	{
		sleep(5);
		kill(fad,SIGINT);
		return 0;
	}
	while(1)
	{
		pause();
	}
	return 0;
}

该段代码执行结果如下:
除此之外进程不带可以向其他进程发送信号还能给自己发送信号。但是给自己发送信号一般使用raise。就不在使用kill了。至于在内核怎样实现这两种处理方式,就在后期的内核分析中再继续说明了。
上面的信号发送,都是即发即收。那么能不能有一种方式我不是马上发送信号而是等待一定的是时间再发送和处理呢?这个肯定是有的,那就是SIGALRM信号。并使用alarm函数设置一个定时器,在未来的某个时刻等待定时器超时,一旦超时就发生SIGALRM信号。(该部分就不再过多的使用编程实现了)


上面是对单一的信号进行处理,如果一个程序需要注册很多信号,那么是否有一个办法可以用一个机制集中管理呢?这就是接下来要说的信号集。
信号集使用sigset_t数据类型表示。针对信号集系统定义了5个处理函数。
sigemptyset:初始化信号集,并全部清除
sigfillset:这个和上面的想反,这个函数是设置使其包含系统中全部的信号
sigaddset:增加一个信号
sigdelset:删除一个信号
sigmember:查看是否包含指定的信号
(以上几种函数可以使用man在系统中查看,这里就不详细的粘贴)

目前信号处理就写到这里,但是信号处理还有一些需要扩充,这个在后期的学习中更加深入的学习和扩展。()

(后期更新……)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值