Linux进程的软中断通信(signal和kill)_进程软中断通信-程序员宅基地

技术标签: 软中断通信  Linux  c语言  linux  多线程  

一、软中断信号

软中断信号( s i g n a l signal signal,又简称为信号)用来通知进程发生了事件。进程之间可以通过调用kill函数发送软中断信号。 L i n u x Linux Linux 内核也可能给进程发送信号,通知进程发生了某个事件(例如内存越界)。
注意:信号只是用来通知某进程发生了什么事件,无法给进程传递任何数据,进程对信号的处理方法有三种:
① 忽略某个信号,对该信号不做任何处理,就像未发生过一样。
② 设置中断的处理函数,收到信号后,由该函数来处理。
③ 对该信号的处理采用系统的默认操作,大部分的信号的默认操作是终止进程。

常用信号

信号名 信号值 发出信号的原因
SIGINT 2 键盘中断 ctrl + c
SIGTERM 15 采用kill 进程编号killall 程序名通知程序
SIGKILL 9 采用kill -9 进程编号强制杀死程序

常用信号处理方法

信号处理方法 作用
SIG_IGN 忽视信号
SIG_DFL 默认的信号处理程序

更具体内容下文会提及


二、函数介绍

(1)wait函数

#include<sys/types.h>
#include<wait.h>		//头文件
pid_t wait(int *status)		//函数原型pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)

wait函数作用是阻塞父进程,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了子进程,即调用成功,wait就会收集这个子进程的信息,并把它彻底销毁后返回被收集的子进程的进程ID;如果调用进程没有子进程,调用就会失败,此时wait返回 − 1 -1 1
因此wait函数有三个功能:
① 阻塞父进程,等待子进程退出。
② 回收子进程残留资源。
③ 获取子进程结束状态(即返回值)。
参数 s t a t u s status status 用来保存被收集进程退出时的一些状态,它是一个指向 i n t int int 类型的指针。如果只是把子进程消灭掉,则设定这个参数为 N U L L NULL NULL 0 0 0 就可以了,即wait(NULL)wait(0)

wait函数一旦被调用,就会一直阻塞在这里,直到有一个子进程退出出现为止。


(2)signal函数

#include<signal.h>		//头文件
void (*signal(int sig, void (*func)(int)))(int)		//函数原型
sighandler_t signal(int signum, sighandler_t handler)	//用typedef处理过的signal函数

signal函数可以设置程序对信号的处理方式。
(对 t y p e d e f typedef typedef 处理过的函数进行说明)
参数 s i g n u m signum signum 表示信号的编号。
参数 h a n d l e r handler handler 表示信号的处理方式,有三种情况:
SIG_IGN:忽略参数 s i g n u m signum signum所指的信号。
② 一个自定义的处理信号的函数,信号的编号为这个自定义函数的参数。
SIG_DFL:恢复参数 s i g n u m signum signum所指信号的处理方法为默认值。
这里不解释其返回值,它的返回值对本次内容关系不大


(3)sleep函数

#include<unistd.h>		//头文件
unsigned int sleep (unsigned int seconds)	//函数原型

进程执行挂起一段时间,也就是等待一段时间在继续执行。(参数 s e c o n d s seconds seconds单位为秒)


(4)kill函数

#include<sys/types.h>
#include<signal.h>		//头文件
int kill(pid_t pid, int sig)		//函数原型

kill函数用于在程序中向其它进程或者线程发送信号。
参数 p i d pid pid 有几种情况:
p i d > 0 pid > 0 pid>0 将信号传给进程号为 p i d pid pid 的进程。
p i d = 0 pid=0 pid=0将信号传给和目前进程相同进程组的所有进程,常用于父进程给子进程发送信号,注意,发送信号者进程也会收到自己发出的信号。
p i d = − 1 pid=-1 pid=1 将信号广播传送给系统内所有的进程,例如系统关机时,会向所有的登录窗口广播关机信息。
参数 s i g sig sig 用作准备发送的信号代码。
返回值: 成功执行时,返回 0 0 0;失败时返回 − 1 -1 1

对于pid的值的理解可以参考:
https://blog.csdn.net/weixin_45920385/article/details/109555124


三、示例

(1)

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

int wait_flag;
void stop();

int main() 
{
    
	int pid1,pid2;
	wait_flag = 1;
	signal(2,stop);
	while(wait_flag == 1);
	while((pid1 = fork()) == -1);
	if(pid1>0) 
	{
    
		while((pid2 = fork()) == -1);
		if(pid2  >  0) 
		{
    
			wait_flag = 1;
			sleep(5);
			kill(pid1,16);
			kill(pid2,17);
			wait(0);
			wait(0);
			printf("Parent process is killed !!\n");
			exit(0);
		}
		else 
		{
    
			wait_flag = 1;
			signal(17,stop);
			while(wait_flag == 1);
			printf("Child process 2 is killed by parent !!\n");
			exit(0);
		}
	}
    else 
    {
    
		wait_flag = 1;
		signal(16,stop);
		while(wait_flag == 1);
		printf("Child process 1 is killed by parent !!\n");
		exit(0);
	}
}

void stop() 
{
    
	wait_flag = 0;
}

运行结果:
在这里插入图片描述

看运行结果可以看出“Child process 2 is killed by parent !!”和“Child process 1 is killed by parent !!”的次序会变化,而“Parent process is killed !!”次序不会变,总是在最后输出。

分析:
signal(2,stop)的作用是键盘输入ctrl + c这个信号后,会调用stop函数,因此 wait_flag 赋予为 0 0 0,因此可退出 16 16 16行的while这个循环,下一步创建子进程(称作子进程①);首先看向父进程①父进程①再创建一个子进程(称作子进程②);先看父进程②,因 p i d 2 > 0 pid2>0 pid2>0,因此从 23 23 23行开始执行,运行sleep(5)等待 5 5 5秒后 (也可以输入ctrl + c跳过) ,执行两个kill语句,把信号码 16 16 16 17 17 17分别传给 I D ID ID p i d 1 pid1 pid1 的进程(即子进程①)和 I D ID ID p i d 2 pid2 pid2 的进程(即子进程②),然后遇到 27 27 27行的wait(0)父进程②进入等待,需要等待子进程2执行完毕;看向子进程②,因 p i d 2 = 0 pid2=0 pid2=0,因此从 34 34 34行开始执行,因为收到kill发来的信号码 17 17 17而执行singal(17,stop)函数后调用stop函数,使得wait_flag = 0 =0 =0,跳出 36 36 36行的while循环,打印出“Child process 2 is killed by parent !!”语句;子进程②执行完回到父进程②,执行 28 28 28行的wait(0)进入等待,需要先执行完子进程①;对于子进程①,从 43 43 43行开始执行,因为收到kill发来的信号码 16 16 16,同理可以知道最后会打印“Child process 1 is killed by parent !!”;再次回到父程序②,执行 29 29 29行打印“Parent process is killed !!”。因此我们从这个过程可以知道“Parent process is killed !!”语句肯定是最后打印出来的,另外两条打印部分的语句是同时进行,运行多次的次序是不同的。
在这里插入图片描述


(2)

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

int wait_flag;
void stop();

int main() 
{
    
	int pid1,pid2,pid3;
	wait_flag = 1;
	signal(2,stop);
	while(wait_flag == 1);
	while((pid1 = fork()) == -1);
	if(pid1>0) 
	{
    
		while((pid2 = fork()) == -1);
		if(pid2  >  0) 
		{
    
			while((pid3 = fork()) == -1);
			if(pid3 > 0)
			{
    
				wait_flag = 1;
				sleep(5);
				kill(pid1,16);
				kill(pid2,17);
				kill(pid3,18);
				wait(0);
				wait(0);
				wait(0);
				printf("Parent process is killed !!\n");
				exit(0);
			}
			else
			{
    
				wait_flag = 1;
				signal(18,stop);
				while(wait_flag == 1);
				printf("Child process 3 is killed by parent !!\n");
				exit(0);
			}
		else 
		{
    
			wait_flag = 1;
			signal(17,stop);
			while(wait_flag == 1);
			printf("Child process 2 is killed by parent !!\n");
			exit(0);
		}
	}
    else 
    {
    
		wait_flag = 1;
		signal(16,stop);
		while(wait_flag == 1);
		printf("Child process 1 is killed by parent !!\n");
		exit(0);
	}
}

void stop() 
{
    
	wait_flag = 0;
}

运行结果:
在这里插入图片描述

看运行结果可以看出“Child process 2 is killed by parent !!”、“Child process 1 is killed by parent !!”和“Child process 3 is killed by parent !!”的次序会变化,而“Parent process is killed !!”次序不会变,总是在最后输出,和上面第一个的代码示例相似。

分析:
对于第一个代码示例多了一个进程组,稍微变得复杂一点,不过具体思路也是一样的。
在这里插入图片描述


需要转载请标明出处

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45920385/article/details/109694050

智能推荐

OpenCV的GrabCut函数使用和源码解读_有了算法模型源码怎么用函数表示-程序员宅基地

文章浏览阅读1.2w次。上一文对GrabCut做了一个了解。OpenCV中的GrabCut算法是依据《"GrabCut" - Interactive Foreground Extraction using Iterated Graph Cuts》这篇文章来实现的。现在我对源码做了些注释,以便我们更深入的了解该算法。一直觉得论文和代码是有比较大的差别的,个人觉得脱离代码看论文,最多能看懂70%,剩下20%或者更多就需要_有了算法模型源码怎么用函数表示

ORA-39002/ORA-29070/ORA-29283/ORA-06512/ORA-29283错误-程序员宅基地

文章浏览阅读6.1k次。C:\Documents and Settings\Administrator>expdp bizdata/bizdata@bzdata schemas=bizdata directory=dd dumpfile=test.dmpExport: Release 10.2.0.1.0 - Production on 星期四, 30 7月, 2009 16:37:12Copyrig_ora-29070

iOS-基于AVPlayer的视频播放器代码封装-0-需求分析与框架设计阶段_ios 播放器架构设计-程序员宅基地

文章浏览阅读513次。视频播放器的需求1>基本功能: 1.对转屏的支持 2.手势调节 3.预览功能 4.缓冲进度、播放进度 2>拓展功能: 1.截屏功能 2.录屏功能 3.Picture in Picture的支持 4.AirPlay的支持1.1 转屏的支持 iPhone下,进入视频页面默认是横屏,如果系统设置支持自动旋_ios 播放器架构设计

CentOS 6的yum源配置(最新地址)_centos6 yum源-程序员宅基地

文章浏览阅读4.8k次,点赞2次,收藏6次。centos6最新源_centos6 yum源

Thread类创建线程_第1关:创建线程-程序员宅基地

文章浏览阅读3.3k次。1.在java中执行多线程编辑在java标准库中,给我们提供了一个标准的Thread类,来操作线程。Thread 类也可以视为是 Java 标准库提供的 API(API:Thread 类提供的方法 和 类)。当我们创建好Thread对象,其实和操作系统中的线程是相对应的。即如果我们想要先创建一个线程,就要先创建一个Thread类的对象。1.1通过Thread类创建线程首先我们先创建子类,让其继承Thread,并且重写run方法我们这里的创建线程都是在同一个进程内部实现的。另外.._第1关:创建线程

超小体积5G模块SIM8202G-M2_5g模组接口以m2为主?-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏6次。7月29日,第十四届国际物联网博览会如期在深圳拉开帷幕。作为疫情期间物联网行业首个大型线下展览,博览会迎来了业内众多的生态合作伙伴。芯讯通携多款产品参加了博览会,并在会上进行了超小尺寸5G模组SIM8202G-M2的全球首发。SIM8202G-M2是一款多频段小尺寸的5G 模组,具有全新的四天线设计。30*42mm的封装尺寸,可以较好满足对尺寸要求较高的终端产品的需求。至此,芯讯通已经推出SIM8200EA-M2,SIM8200CE-M2,采用LGA封装的SIM8200G以及支持毫米波的SIM8300G-_5g模组接口以m2为主?

随便推点

S32DS Components组件配置-程序员宅基地

文章浏览阅读3.5k次,点赞3次,收藏21次。S32DS Components组件配置_s32ds components

Golang 调用http 文件上传接口 进行上传文件_golang http send file-程序员宅基地

文章浏览阅读6.9k次,点赞2次,收藏5次。远程服务器有一个文件上传接口,文件用于保存到服务器本地,用go如何调用此接口将文件上传至服务器?首先,文件上传请求方 与 接收方 要协调工作(解析等工作)接收方:func UploadFileToLocal(c echo.Context) error { r := c.Request() //无论用的什么路由,原理是要从request获取数据 t := echotools...._golang http send file

C# WPF上位机开发(内嵌虚拟机的软件开发)_c#wpf开发上位机设计器软件-程序员宅基地

文章浏览阅读1.2k次,点赞16次,收藏7次。【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 学习过halcon的同学都知道,它不仅有很多的图像算子可以使用,而且调试很方便。每一步骤的调试结果,都可以看到对应的显示效果。这中间,开发者可以自己调参数、写脚本,十分方便。在所有的配置都ok之后,直接导出为c、c# code,变成最终的软件输出,部署到客户的电脑上面。 其实要做到这一点,也不是很复杂。一种比较简单的办法,就是内嵌一个lua虚拟机,把对应的函数转成l_c#wpf开发上位机设计器软件

做GLB外推最快多久能见效-程序员宅基地

文章浏览阅读329次,点赞9次,收藏8次。GNB外链的群发模式,保证了大量链接的发放,同时维持了dofollow比例在10%左右,有助于维护健康的外链结构比例。不要仅限于单一平台或渠道,应通过多渠道综合推广,扩大覆盖范围,提高品牌或产品的知名度,从而加速推广效果的显现。GLB外推通过在互联网上的多个渠道发布信息,借助社交媒体的传播力量,迅速提升品牌或产品的在线可见度。不同的平台有其特定的受众群体和传播特性,因此,选择与目标市场和受众匹配的平台可以加快推广效果的显现。这些策略的协同作用,将为外贸网站带来更大的流量和更好的品牌曝光度。

apt-get命令 – 安装软件_apt-get安装httpd-tools-程序员宅基地

文章浏览阅读3.7k次。apt-get命令是Debian Linux发行版中的APT软件包管理工具。所有基于Debian的发行都使用这个包管理系统。deb包可以把一个应用的文件包在一起,大体就如同Windows上的安装文件。_apt-get安装httpd-tools

AES/ECB/PKCS5Padding/PKCS7Padding 128位密钥(带密钥补位功能)加密解密-程序员宅基地

文章浏览阅读4.4w次,点赞8次,收藏27次。今天客户说发解密算法过来,本来以为拿来的是代码直接用,没想到就直接给了我个网站http://www.seacha.com/tools/aes.html和他们用的算法模式+密钥。以前还真没玩过AES加密解密,下面是今天研究的结果。实现结果:算法:AES模式:ECB密钥长度:128位密钥:自己填(代码中带补位功能)补码方式:PKCS5Padding/PKCS7P_aes/ecb/pkcs5padding