当前位置: 首页 > 编程日记 > 正文

Linux进程间通信--信号

signal

一、初步理解信号

为了理解信号 ,先从我们最熟悉的场景说起:

1.用户输入命令,在Shell下启动一个前台进程。         

2.用户按下Ctrl-C,这个键盘输入产生一个硬件中断。         

3.如果CPU当前正在执行这个进程的代码,则该进程的用户空间代码暂停执行,CPU从用户态切换到内核态处理硬件断。 

4. 终端驱动程序将Ctrl-C解释成一个SIGINT信号,记在该进程的PCB中(也可以说发送了一个SIGINT信号给该进程)。 

5. 当某个时刻要从内核返回到该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号,发现有一个SIGINT信号待处理,而这个信号的默认处理动作是终止进程,所以直接终止进程而不再返回它的用户空间代码执行。

注意,Ctrl-C产生的信号只能发给前台进程。一个命令 后面加个&可以放到后台运行,这样 Shell不必等待进程结束就可以接受新的命令,启动新的进程。Shell可以同时运行一个前台进 程和任意多个后台进程,只有前台进程才能接到Ctrl-C这种控制键产生的信号。前台进程 在运行过程中用户随时可能按下Ctrl-C而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的

二、用kill -l命令可以察看系统定义的信号列表:


   每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有 定 义#define SIGINT 2。编号34以上的是实时信号,只讨论编号34以下的信号,不讨论实时信号。这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有:

man 7 signal

 

各类信号的说明都有。

三、信号的产生或者发送

  函数可以向一个进程主动地发出一个信号,我们可以通过两个函数kill和alarm来发送一个信号。

1、kill函数
   先来看看kill函数,进程可以通过kill函数向包括它本身在内的其他进程发送一个信号,如果程序没有发送这个信号的权限,对kill函数的调用就将失败,而失败的常见原因是目标进程由另一个用户所拥有。想一想也是容易明白的,你总不能控制别人的程序吧,当然超级用户root。

kill函数的原型为:
#include <sys/types.h>  
#include <signal.h>  
int kill(pid_t pid, int sig);  
它的作用把信号sig发送给进程号为pid的进程,成功时返回0。

kill调用失败返回-1,调用失败通常有三大原因:
1、给定的信号无效(errno = EINVAL)
2、发送权限不够( errno = EPERM )
3、目标进程不存在( errno = ESRCH )

2、alarm函数
   这个函数跟它的名字一样,给我们提供了一个闹钟的功能,进程可以调用alarm函数在经过预定时间后向发送一个SIGALRM信号。

alarm函数的型如下:
#include <unistd.h>  
unsigned int alarm(unsigned int seconds); 
   alarm函数用来在seconds秒之后安排发送一个SIGALRM信号,如果seconds为0,将取消所有已设置的闹钟请求。alarm函数的返回值是以前设置的闹钟时间的余留秒数,如果返回失败返回-1。

下面就给合fork、sleep和signal函数,用一个例子来说明kill函数的用法吧,源文件为,代码如下:
#include <unistd.h>  
#include <sys/types.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <signal.h>  static int alarm_fired = 0;  void ouch(int sig)  
{  alarm_fired = 1;  
}  int main()  
{  pid_t pid;  pid = fork();  switch(pid)  {  case -1:  perror("fork failed\n");  exit(1);  case 0:  //子进程  sleep(5);  //向父进程发送信号  kill(getppid(), SIGALRM);  exit(0);  default:;  }  //设置处理函数  signal(SIGALRM, ouch);  while(!alarm_fired)  {  printf("Hello World!\n");  sleep(1);  }  if(alarm_fired)  printf("\nI got a signal %d\n", SIGALRM);  exit(0);  
}  

在代码中我们使用fork调用复制了一个新进程,在子进程中,5秒后向父进程中发送一个SIGALRM信号,父进程中捕获这个信号,并用ouch函数来处理,变改alarm_fired的值,然后退出循环。
  注:如果父进程在子进程的信号到来之前没有事情可做,我们可以用函数pause()来挂起父进程,直到父进程接收到信号。当进程接收到一个信号时,预设好的信号处理函数将开始运行,程序也将恢复正常的执行。这样可以节省CPU的资源,因为可以避免使用一个循环来等待。以本例子为例,则可以把while循环改为一句pause();

下面再以一个小小的例子来说明alarm函数和pause函数的用法吧,源文件名为,signal4.c,代码如下:
#include <unistd.h>  
#include <sys/types.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <signal.h>  static int alarm_fired = 0;  void ouch(int sig)  
{  alarm_fired = 1;  
}  int main()  
{  //关联信号处理函数  signal(SIGALRM, ouch);  //调用alarm函数,5秒后发送信号SIGALRM  alarm(5);  //挂起进程  pause();  //接收到信号后,恢复正常执行  if(alarm_fired == 1)  printf("Receive a signal %d\n", SIGALRM);  exit(0);  
} 

进程在5秒后接收到一个SIGALRM,进程恢复运行,打印信息并退出。

四、信号的处理
1.signal函数:

程序可用使用signal函数来处理指定的信号,主要通过忽略和恢复其默认行为来工作。signal函数的原型如下:
#include <signal.h>  
void (*signal(int sig, void (*func)(int)))(int); 
这是一个相当复杂的声明,耐心点看可以知道signal是一个带有sig和func两个参数的函数,func是一个类型为void (*)(int)的函数指针。该函数返回一个与func相同类型的指针,指向先前指定信号处理函数的函数指针。准备捕获的信号的参数由sig给出,接收到的指定信号后要调用的函数由参数func给出。其实这个函数的使用是相当简单的,通过下面的例子就可以知道。注意信号处理函数的原型必须为void func(int),或者是下面的特殊值:
SIG_IGN:忽略信号
SIG_DFL:恢复信号的默认行为
说了这么多,还是给出一个例子来说明一下吧,代码如下:

运行结果:

可以看到,第一次按下终止命令(ctrl+c)时,进程并没有被终止,面是输出OUCH! - I got signal 2,因为SIGINT的默认行为被signal函数改变了,当进程接受到信号SIGINT时,它就去调用函数ouch去处理,注意ouch函数把信号SIGINT的处理方式改变成默认的方式,所以当你再按一次ctrl+c时,进程就像之前那样被终止了。

2.sigaction函数

前面我们看到了signal函数对信号的处理,但是一般情况下我们可以使用一个更加健壮的信号接口—sigaction函数。它的原型为:
#include <signal.h>  
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);  
该函数与signal函数一样,用于设置与信号sig关联的动作,而oact如果不是空指针的话,就用它来保存原先对该信号的动作的位置,act则用于设置指定信号的动作。

sigaction结构体定义在signal.h中,但是它至少包括以下成员:
1.void (*) (int) sa_handler;处理函数指针,相当于signal函数的func参数。
2.sigset_t sa_mask; 指定一个,信号集,在调用sa_handler所指向的信号处理函数之前,该信号集将被加入到进程的信号屏蔽字中。信号屏蔽字是指当前被阻塞的一组信号,它们不能被当前进程接收到。
3.int sa_flags;信号处理修改器;

4.sa_mask的值通常是通过使用信号集函数来设置的。
5.sa_flags,通常可以取以下的值:


   现在有一个这样的问题,我们使用signal或sigaction函数来指定处理信号的函数,但是如果这个信号处理函数建立之前就接收到要处理的信号的话,进程会有怎样的反应呢?它就不会像我们想像的那样用我们设定的处理函数来处理了。sa_mask就可以解决这样的问题,sa_mask指定了一个信号集,在调用sa_handler所指向的信号处理函数之前,该信号集将被加入到进程的信号屏蔽字中,设置信号屏蔽字可以防止信号在它的处理函数还未运行结束时就被接收到的情况,即使用sa_mask字段可以消除这一竞态条件。

承接上面的例子,下面给出用sigaction函数重写的例子代码,代码如下:
#include <unistd.h>  
#include <stdio.h>  
#include <signal.h>  void ouch(int sig)  
{  printf("\nOUCH! - I got signal %d\n", sig);  
}  int main()  
{  struct sigaction act;  act.sa_handler = ouch;  //创建空的信号屏蔽字,即不屏蔽任何信息  sigemptyset(&act.sa_mask);  //使sigaction函数重置为默认行为  act.sa_flags = SA_RESETHAND;  sigaction(SIGINT, &act, 0);  while(1)  {  printf("Hello World!\n");  sleep(1);  }  return 0;  
}  
运行结果与前一个例子中的相同。注意sigaction函数在默认情况下是不被重置的,如果要想它重置,则sa_flags就要为SA_RESETHAND。

关于信号总结到此,进程通信其他机制见博主另外博文。
赐教!

转载于:https://www.cnblogs.com/melons/p/5791795.html

相关文章:

如何优化cocos2d程序的内存使用和程序大小:第一部分

译者&#xff1a; 在我完成第一个游戏项目的时候&#xff0c;我深切地意识到“使用cocos2d来制作游戏的开发者们&#xff0c;他们大多会被cocos2d的内存问题所困扰”。而我刚开始接触cocos2d的时候&#xff0c;社区里面的人们讨论了一个非常有意义的话题&#xff1a;“请简单地…

UILayer的一些属性

iOS创建UIView是直接在Core Animation layers上进行绘制&#xff0c;每一个UIView实例都会自动创建CALayer的实例&#xff0c;并且设置为UIView实例的layer属性。 以下事例通过设置UIImageView的layer&#xff0c;实现阴影、圆角、边框和旋转缩放等效果 -(void)initImgView{UI…

Hive的基本应用

实验 目的 要求 目的&#xff1a; 了解Hive架构&#xff0c;掌握Hive环境部署&#xff1b;了解Hive与Hadoop及传统关系型数据库的对比&#xff1b;掌握Hive中DDL和DML的使用&#xff1b;了解Hive高级应用&#xff1b;Hive内置函数使用及Hive自定义函数&#xff1b;了解Hive常…

template

//引入包<script type"text/javascript" src../template.js></script> //定义一个有ID的script标签&#xff1a;<script idtem type"text/html"> <h4>{{name}}</h4> <ul> {{each films as value}} <li> <str…

UICollectionView的基本使用(1)

如果是简单实用UICollectionView的话&#xff0c;用法和UITableView基本一致。下面是用UICollectionView实现的简单图片显示 &#xff08;1&#xff09;打开storyboard&#xff0c;将一个UICollectionView拖到View Controller Scene中&#xff0c;默认的UICollectionView已经包…

SQL Server的数据库连接的极限在哪儿?

在软件设计中&#xff0c;关于多层的设计&#xff0c;有一部份是有关数据库的。 设计上分成这样三层 客户端UI -- 应用服务器 -- 数据库服务器 有个说法是&#xff0c;可以在应用服务器这一层共享使用数据库连接池&#xff0c;从而减轻数据库服务器的负担。 我查了好多资料&…

Docker的使用(五:Docker中的网络与数据管理)

实验环境 三台运行有Ubuntu 16.04 操作系统的虚拟机&#xff0c;并每台主机中已安装docker环境&#xff1b; 学习目标 docker的网络管理docker Swarm集群的使用Volume数据卷的使用 实验内容 任务一&#xff1a;Docker网络管理 1、Docker默认网络管理 docker安装时自动创建…

Java中单元测试中:@BeforeClass,@Before,@Test,@After,@AfterClass中的问题详解

在Junit4中还有的测试注解有&#xff1a; BeforeClass &#xff0c;Before&#xff0c;Test&#xff0c;After&#xff0c;AfterClass 1、其中&#xff1a;BeforeClass&#xff0c;AfterClass是Junit4中新添加进去的 2、如果Run as --->Junit Test&#xff0c;运行含有Test…

iOS开发流程总结

本文由社区会员umyueyue分享 以下是会员umyueue总结的iOS开发流程以及学习中的资料分享。 流程&#xff1a;注册、开发、真机测试、发布以及上线。 iPhone iOS 4从注册到app上线开发流程 http://blog.csdn.net/linzhiji/article/details/6732868 一、关于注册账号IDP和Apple ID…

(2)iOS用UICollectionView实现Gallery效果

本文主要实现&#xff1a; &#xff08;1&#xff09;用UICollectionView显示一组图片 &#xff08;2&#xff09;左右滑动来浏览所有图片 &#xff08;3&#xff09;图片自动对齐到网格&#xff08;即滑动停止后中间的图片对齐到正中位置&#xff09; &#xff08;4&#…

Docker的使用(docker pull拉取镜像失败问题解决)

在docker拉取Nginx镜像过程中&#xff0c;速度慢&#xff0c;或者不成功 报错代码&#xff1a; Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting hea…

java,js,jstl,EL的简单交互

EL全名Expression Language.EL提供了在JSP脚本编制元素范围外使用运行时表达式的功能。 脚本编制元素是指页面中能够用于在JSP文件中嵌入java代码的元素。 JSP标准标记库&#xff08;jsp staandard tag library&#xff0c;jstl&#xff09;是一个实现web应用程序常用功能的定制…

iOS UICollectionView实现瀑布流(3)

前面两篇Blog简单的介绍了UICollection的基本使用并实现了类似Android的Gallery效果&#xff0c;这篇文章使用UICollection来实现瀑布流效果&#xff0c;代码主要是在极客学院Carol老师的视频&#xff0c;并在提供的demo下直接修改代码&#xff0c;进行屏幕适配&#xff0c;最终…

LevelDb系列之简介

说起LevelDb也许您不清楚&#xff0c;但是如果作为IT工程师&#xff0c;不知道下面两位大神级别的工程师&#xff0c;那您的领导估计会Hold不住了&#xff1a;Jeff Dean和Sanjay Ghemawat。这两位是Google公司重量级的工程师&#xff0c;为数甚少的Google Fellow之二。 Jeff De…

Spark集群启动时worker节点启不起来

在spark集群中使用命令&#xff1a; sbin/start-all.sh 启动集群时报错&#xff1a; starting org.apache.spark.deploy.master.Master, logging to /home/yxk/cluster/spark/logs/spark-yxk-org.apache.spark.deploy.master.Master-1-linux.out yxklinuxs password: linux:…

XML xmlns

xmlns xml namespaces 参考 http://www.w3school.com.cn/tags/tag_prop_xmlns.asp http://www.w3school.com.cn/xml/xml_namespaces.asp <table><tr>这是一行</tr> </table><table><material>黄花梨</material> </table> 放到…

StarlingMVC简介,原理解说及示例源码

StarlingMVC简介 StarlingMVC是一个为使用Starling来开发游戏的MVC框架。这个框架的特性方面&#xff0c;很像Swiz和RobotLegs&#xff0c;原理亦像Mate。其特性列表如下&#xff1a; 依赖注入(DI)/控制反转(IOC)视图代理(View Mediation)事件捕获(Event Handling)非侵入性框架…

iOS调用系统相机文字改为中文

只要把这里改成China&#xff1a;

微服务项目的整合与测试

实验目的 掌握微服务项目的整合使用 掌握Swagger-UI的简单使用 练习内容 1、微服务项目整合 1.1、项目预览 1.1.1、在 https://github.com/shi469391tou/microservice-mallmanagement.git 地址下载&#xff0c;并导入Myeclipse中&#xff1b; 1.1.2、查看项目的结构 1.2、…

mysql单表多timestamp的current_timestamp设置问题

一个表中出现多个timestamp并设置其中一个为current_timestamp的时候经常会遇到 1293 - Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause 原因是当你给一个timestamp设置为on update current_time…

iOS 关于Blocks

*本文参考了《Objective-C高级编程 iOS与OSX多线程和内存管理》一书&#xff0c;关于Block的介绍摘取自此书。 Objective-c 语言中Block语法格式为&#xff1a; 返回值类型 参数列表 表达式 c语言中的函数语法格式为 返回值类型 函数方法名 参数列表 表达式 从上面的…

一步步写STM32 OS【二】环境搭建

一、安装IAR for ARM6.5 二、新建工程 1、选择处理器&#xff1a;STM32F407VG&#xff0c;暂不使用FPU2、必要的路径配置和宏定义3、使用SWO重定向IO输出4、使用ST-LINK仿真器5、下载配置6、设置CPU频率&#xff0c;防止SWO输出乱码三、代码调试 四、工程下载 stepbystep_stm32…

微服务项目的部署

练习目标 掌握Docker Compose编排工具的使用掌握微服务项目与Docker的整合方式掌握微服务项目的部署方式 项目整合参考&#xff1a;https://blog.csdn.net/qq_37823605/article/details/91379272 练习内容 1、Docker Compose编排工具 1.1、Docker Compose的安装与卸载 1.1…

CSS 布局:40个教程、技巧、例子和最佳实践

前言&#xff1a; 布局是WEB开发一个重要的课题&#xff0c;进入XHTML/CSS后&#xff0c;使用TABLE布局的方式逐渐淡出&#xff0c;CSS布局以众多优点成为主流&#xff0c;本文将介绍40个基于CSS的web布局的资源和教程。文章的出处在http://www.noupe.com/css/css-layouts-40-t…

【仿去哪儿登录】UITextField输入时检查输入框是否为空

APP登录时&#xff0c;一般是是等用户输入完账号和密码后才去检查是否为空&#xff0c;而去哪儿登录时&#xff0c;在账号和密码的输入过程中&#xff0c;只要当账号和密码其一为空时&#xff0c;登录按钮立即变成不可用&#xff08;图1&#xff09;&#xff0c;只有账号和密码…

sql排名语句

查询全部 select dwmc,pjdf,row_number() over(order by pjdf desc) as paiming from Sab_hhb_zhb inner join jgdx on jgdx.midSab_hhb_zhb.mid查询单个select paiming from (select mid,pjdf,row_number() over(order by pjdf desc) as paiming from Sab_hhb_zhb ) Sab_hhb_z…

Sqoop的基础应用

实验目的要求 了解ET了工具Sqoop&#xff1b;学会安装配置Sqoop&#xff1b;学会使用数据迁移框架Sqoop&#xff1b;使用Sqoop导入MySQL到HDFS和Hive&#xff1b;使用Sqoop导出HDFS数据到MySQL&#xff1b; 实验环境 Java jdk 1.7&#xff1b;apache-maven-3.6.0&#xff1b;…

hadoop程序MapReduce之SingletonTableJoin

需求&#xff1a;单表关联问题。从文件中孩子和父母的关系挖掘出孙子和爷奶关系 样板&#xff1a;child-parent.txt xiaoming daxiong daxiong alice daxiong jack 输出&#xff1a;xiaoming alice xiaoming jack 分析设计&#xff1a; mapper部分设计&#xff1a; 1、<k1,…

Android网络框架Volley的快速使用

一.基本使用 之前做Android开发都是使用学长自己封装好的网络请求框架&#xff0c;第三方网络框架也很多&#xff0c;网上搜索了一下&#xff0c;大多数人推荐使用 android-async-httpokhttpVolley 其中Volley是Google推出了官方的针对Android平台上的网络通信库&#xff0c;能…

浏览器版本过低

http://study.163.com/common/errors/notSupported.htm <div class"wb f-cb"> <a href"http://www.google.cn/intl/zh-CN/chrome/browser/" class"g f-hide" target"_blank">谷歌浏览器</a> <a href"http:/…