linux内核剖析(九)进程间通信之-信号signal

信号及信号来源

什么是信号

信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。但它们还可以作为进程间通信或修改行为的一种方式,明确地由一个进程发送给另一个进程。一个信号的产生叫生成,接收到一个信号叫捕获。

信号本质

信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。

信号来源

信号事件的发生有两个来源

  • 硬件来源(比如我们按下了键盘或者其它硬件故障);
  • 软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。

信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了那些系统事件。

如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递个它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞取消时才被传递给进程。

linux产生信号的条件

  1. 当用户按某些终端键时,将产生信号。
    终端上按”Ctrl+c”组合键通常产生中断信号 SIGINT,终端上按”Ctrl+\”键通常产生中断信号 SIGQUIT,终端上按”Ctrl+z”键通常产生中断信号 SIGSTOP 等。
  2. 硬件异常将产生信号。
    比如数据运算时,除数为0;或者无效的存放访问等.这些条件通常由硬件检测到,并通知内核,然后内核为该条件发生时正在运行的进程产生适当的信号.。
  3. 软件异常将产生信号。
    当检测到某种软件条件已发生,并将其通知有关进程时,产生信号。
  4. 调用 kill() 函数将发送信号。
    注意:接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户。
  5. 运行 kill 命令将发送信号。
    此程序实际上是使用 kill 函数来发送信号。也常用此命令终止一个失控的后台进程。

信号的捕获和处理

若内核(空间)向用户空间(进程)发出某个信号时,用户空间(进程)可按照下列3中方式来面对:

  1. 忽略信号,即对信号不做任何处理
    大多数信号都可以使用这种方式处理,但信号SIGKILL和SIGSTOP绝不能被忽略.因为它们向超级用户提供了一种使进程终止的可靠方法.

  2. 缺省动作,执行信号的默认动作.大多数信号的系统默认动作是终止在进程.

  3. 捕捉信号,定义信号处理函数,当信号发生时,执行相应的处理函数;

注意,进程对实时信号的缺省反应是进程终止。

Linux究竟采用上述三种方式的哪一个来响应信号,取决于传递给相应API函数的参数。

信号是一种软件中断机制,即当信号发生时,必须用中断的方法告诉内核”请执行下列操作”.

在linux终端内输入 kill -l可以查看系统所支持的信号.可以看出,每个信号的名字都是以SIG开头.

linux内核剖析(九)进程间通信之-信号signal

在头文件signal.h(/usr/include/bits/signum.h)中,这些信号都被定义为正整数,即每个信号和一个数字编码相对应.

不同的架构,文件存储路径可能不同可以使用 sudo find /usr/include -name signum.h查找

我的位于 /usr/include/x86_64-linux-gnu/bits/signum.h

linux内核剖析(九)进程间通信之-信号signal

其中SIGRTMIN,SIGRTMAX定义如下

#define SIGRTMIN        (__libc_current_sigrtmin ())
#define SIGRTMAX        (__libc_current_sigrtmax ())

linux内核剖析(九)进程间通信之-信号signal

linux信号的发展及种类

可以从两个不同的分类角度对信号进行分类:

  1. 可靠性方面:可靠信号与不可靠信号;
  2. 与时间的关系上:实时信号与非实时信号。

可靠信号与不可靠信号

“不可靠信号”

Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做”不可靠信号”,信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是”不可靠信号”的来源。

它的主要问题是:
进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;

因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。

信号可能丢失,后面将对此详细阐述。

因此,早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失。

Linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。因此,Linux下的不可靠信号问题主要指的是信号可能丢失。

可靠信号

随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。所以,后来出现的各种Unix版本分别在这方面进行了研究,力图实现”可靠信号”。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。

同时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。

POSIX.4对可靠信号机制做了标准化。但是,POSIX只对可靠信号机制应具有的功能以及信号机制的对外接口做了标准化,对信号机制的实现没有作具体的规定。

信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。

Linux在支持新版本的信号安装函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。


不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。

事实上,可靠信号是指后来添加的新信号(信号值位于SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号。

信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。

对于目前linux的两个信号安装函数:signal()及sigaction()来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数(对所有信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。

实时信号与非实时信号

早期Unix系统只定义了32种信号,Ret hat7.2支持64种信号,编号0-63(SIGRTMIN=31,SIGRTMAX=63),将来可能进一步增加,这需要得到内核的支持。

前32种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反应就是进程终止。后32个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都被接收。实时信号是POSIX标准的一部分,可用于应用进程。

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

信号的发送

发送信号的主要函数有: kill()raise()sigqueue()alarm()setitimer()以及 abort()

kill–传送信号给指定进程

使用man 2 kill查看帮助信息

linux内核剖析(九)进程间通信之-信号signal

函数原型

#include
#include
int kill(pid_t pid,int signo)

参数说明

  • 第一个参数pid:指定发送信号的接收线程
  • 第二个参数signo:信号的signum

参数pid

参数pid的值信号的接收进程 pid>0 进程ID为pid的进程 pid=0 同一个进程组的进程 pid

Original: https://www.cnblogs.com/alantu2018/p/8991365.html
Author: AlanTu
Title: linux内核剖析(九)进程间通信之-信号signal

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/8568/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Git 移动操作

    [tom@CentOS project]$ pwd /home/tom/project [tom@CentOS project]$ ls README string string….

    Linux 2022年8月30日
    0260
  • error: dereferencing pointer to incomplete type

    调试显示驱动,打印of_node信息出现的错误; /****************************************************************…

    Linux 2022年8月30日
    0230
  • 【Linux基础】正则表达式

    1.正则表达式 正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),是由普通字符(例如字符 a 到 z)以及特殊字符(称为”…

    Linux 2022年8月13日
    0330
  • Git 解决本地远端版本冲突

    It’s not who you are underneath, it’s what you do that defines you Brick walls…

    Linux 2022年8月30日
    0240
  • [Linux]SVN忽略文件夹更新的命令与方法

    有时,您需要忽略对服务器上的文件夹及其内容的更新。您可以使用以下命令: [En] Sometimes you need to ignore updates to a folder …

    2022年8月26日
    0240
  • jenkins pipeline中获取shell命令的输出

    //获取标准输出//第一种result = sh returnStdout: true ,script: ” Original: https://www.cnblogs…

    Linux 2022年9月14日
    0150
  • oracle怎么恢复被覆盖的存储过程

    原理很简单,存储过程的定义就是数据字典,修改数据字典跟修改普通表的数据没有区别,此时会把修改前的内容放到undo中,可以根据这一点来进行闪回,所以我说要尽快,要不然找不回来了。 来…

    Linux 2022年8月20日
    0300
  • 哨兵+redis主从部署架构-docker部署

    架构图 哨兵的介绍 sentinel , 中文是哨兵。 哨兵是redis 集群架构中非常重要的一个组件,主要功能如下: (1)集群监控:负责监控reidis master 和sla…

    Linux 2022年9月14日
    0220
  • Linux:命令执行顺序控制与管道

    顺序执行 简单的顺序命令可以使用符号”;”完成,如:sudo apt-get update;sudo apt-get install some-tool;s…

    Linux 2022年8月24日
    0300
  • 2022.29 Unix和Linux

    Unix诞生于1969年,ken Tphmpson(肯.汤普森)最初用汇编语言编写,后来他和Dennis Ritch(丹尼斯·里奇)一起用高级C语言重写。UNIX 第一次公开露面是…

    Linux 2022年8月24日
    0260
  • Android开发中网络代理设置实用总结

    一、背景 进行Android项目开发时,跟网络代理基本上天天都在打交道。通常情况下,至少有三个场景中经常用到网络代理:1,经常通过Chrome访问Google等国外的技术网站,如通…

    Linux 2022年8月30日
    0280
  • git log 退出之后 log不保留在屏幕上(mac)

    原因在于git使用的是less命令,less默认不像cat一样保留。通过以下命令设置保留 git config –global –replace-all core.pager …

    2022年8月30日
    0270
  • gitlab 建立本地仓库

    1.首先在gitlib上进行注册 注册与登录 为了用户的隐私,我们的私人 GitLab 平台关闭了自主注册。申请 GitLab 账号请联系工作站管理员:liuhaoyang@pku…

    2022年8月30日
    0250
  • PHP自定义函数返回多个值

    有时要求函数返回多个值时,用return是不可以把值一个接一个地输出的。 return语句可以返回任何类型的变量,这就是使自定义函数返回多个值的关键。 代码: function r…

    Linux 2022年8月20日
    0230
  • linux安装pycharm

    1、个人安装环境 ubuntu 18.04.1 2、下载、安装 2.1 下载地址 https://www.jetbrains.com/pycharm/download/#secti…

    Linux 2022年8月24日
    0380
  • shell 递归枚举文件并操作

    递归枚举文件并操作 #!/bin/bash CURDIR=$(cd $(dirname $0); pwd) export GOPATH=$CURDIR/.. echo GOPATH…

    Linux 2022年9月14日
    0230
  • linux安装elasticsearch

    安装步骤 下载ES wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.11.2-l…

    Linux 2022年8月11日
    0560
  • 使用Hexo+Github搭建个人博客网站

    曾几何时,笔者也幻想过写个项目来搭建属于自己的个人博客。但是,写程序以及维护的成本,不禁让我犹豫再三,最后还是选择了CSDN等博客网站。将近三年的博客生涯,我尝试了不同的博客网站,…

    2022年8月30日
    0240
  • redis

    字符串:类似vector,有空闲的空间 capacity和len,当长度小于1M时,每次扩容加倍,大于1M,每次扩容1M,最大512M hash: 相当于c++ unordered…

    Linux 2022年9月14日
    0200
  • Linux select poll源码剖析

    在读select、poll源码前,需要先了解的知识点: 等待队列 文件系统(主要是进程的打开文件描述符表以及struct file) poll机制 资源注册监听poll() -&g…

    Linux 2022年8月24日
    0350
  • Linux常用文件权限命令详解

    pwd pwd命令用于获取当前工作目录的绝对路径。 使用示例: pwd 效果如下图: cd cd命令用于切换工作目录。 使用示例: cd 万&#x73…

    Linux 2022年9月10日
    0240
  • GitLab 内存使用优化

    对 GitLab 做了一次迁移,机器的配置是 4C4G,根据官方配置推荐应该是足够了,因为我们的用户只有 120 个左右。但是不知道为什么上线之后,内存占用率经常超过90%,监控告…

    Linux 2022年8月30日
    0340
  • Redis-Sentinel Redis的哨兵模式

    Redis-Sentinel Redis的哨兵模式Redis Sentinel 模式简介Redis-Sentinel是官方推荐的高可用解决方案,当redis在做master-sla…

    Linux 2022年9月14日
    0220
  • mac如何安装FinalShell

    1、Mac一键安装脚本: curl -o finalshell_install.sh www.hostbuf.com/downloads/finalshell_install.sh…

    Linux 2022年9月14日
    0810
  • linux开发缩写

    1.CONFIG_OF 在一些驱动中经常看到#ifdef CONFIG_OF,这里的OF是Open Firmware。 Open Firmware. This was invent…

    Linux 2022年8月13日
    0320
  • 在Linux下的文件IO操作

    系统调用 系统调用: 操作系统提供给用户程序调用的一组”特殊”接口,用户程序可以通过这组”特殊”接口来获得操作系统内核提供的服务 为…

    Linux 2022年9月10日
    01780

发表回复

登录后才能评论
免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部