Linux系统编程 ----信号详解

Linux 信号


Linux中,信号其实是软件中断,也是进程间通信的最古老的方式。它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。



前言

“中断”就是像从一个事件处理转而处理其他事件,处理完毕后继续处理最开始的事件。“信号"就是属于这么一种“中断"。我们在终端上敲"Ctrl+c"”,就产生一个中断",相当于产生一个信号,接着就会处理这么一个“中断任务”(默认的处理方式为中断当前进程)。。

信号的特点:

  • 简易
  • 无法传递大量数据
  • 触发某种条件才会发送信号

概述


信号可以直接进行用户空间进程和内核空间进程的交互,内核进程可以利用它来通知用户空间进程发生了哪些系统事件。
一个完整的信号周期包括三个部分:信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数。如下图所示:

在这里插入图片描述

这里信号的产生,注册,注销时信号的内部机制,而不是信号的函数实现。


信号编号

Unix早期版本就提供了信号机制,但不可靠,信号可能丢失。Berkeley和AT&T都对信号模型做了更改,增加了可靠信号机制。但彼此不兼容。POSIX.1对可靠信号例程进行了标准化。


kill -l 查看对应信号
在这里插入图片描述

不存在编号为0的信号。其中1-31号信号称之为常规信号(也叫普通信号或标准信号),34-64称之为实时信号,驱动编程与硬件相关。名字上区别不大。而前32个名字各不相同。


信号表

在这里插入图片描述


信号要素

  • 名称
  • 编号
  • 事件
  • 处理动作

man 7 singal 查看

在这里插入图片描述

在标准信号中,有一些信号是有三个"Value",第一个值通常对alpha和sparc架构有效,中间值针对x86.arm和其他架构,最后一个应用于mips架构。一个·表示在对应架构上尚未定义该信号。
不同的操作系统定义了不同的系统信号。因此有些信号出现在Unix系统内,也出现在Linux中,而有的信号出现在FreeBSD或Mac OS中却没有出现在Linux下。这里只研究Linux系统中的信号。


Action

在这里插入图片描述

SIGKILL 和 SIGSTOP 这两个信号是不会被捕捉、阻塞、忽略的。
在这里插入图片描述



信号的状态


信号的产生


当用户按某些终端键时,将产生信号。

Ctrl+c 组合键通常产生中断信号SIGINT
Ctrl+\ 键通常产生中断信号SIGQUIT
Ctrl+z 键通常产生中断信号SIGSTOP

硬件异常将产生信号。

除数为0,无效的内存访问等。这些情况通常由硬件检测到,并通知内核,然后内核产生适当的信号发送给相应的进程。

软件异常将产生信号。

当检测到某种软件条件已发生(如:定时器alarm),并将其通知有关进程时,产生信号。d)调用系统函数(如: kill、raise、abort)将发送信号。

接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户。运行kill /killall命令将发送信号。
此程序实际上是使用kill 函数来发送信号。也常用此命令终止一个失控的后台进程。



阻塞信号集、未决信号集


描述每个进程的结构体task_struct,除了包含进程id,状态,工作目录,用户id,组id文件描述符表,还包含了信号相关的信息,主要指阻塞信号集和未决信号集。

阻塞信号集(信号屏蔽字)

将某些信号加入集合,对他们设置屏蔽,当屏蔽x信号后,再收到该信号,该信号的处理将推后(处理发生在解除屏蔽后)。

未决信号集

信号产生,未决信号集中描述该信号的位立刻翻转为1,表示信号处于未决状态。当信号被处理对应位翻转回为0。这一时刻往往非常短暂。
信号产生后由于某些原因(主要是阻塞)不能抵达。这类信号的集合称之为未决信号集。在屏蔽解除前,信号处于未决状态。



信号相关函数



kill 函数

给指定进程发送指定信号
在这里插入图片描述

参数:
pid :取值有4种情况∶

  • pid > 0:将信号传送给进程ID为pid的进程。
  • pid = 0:将信号传送给当前进程所在进程组中的所有进程。
  • pid = -1:将信号传送给系统内所有的进程。
  • pid < -1︰将信号传给指定进程组的所有进程。这个进程组号等于pid的绝对值。

sig :

信号的编号,这里可以填数字编号,也可以填信号的宏定义,可以通过命令ki11 - 1("1”为字母)进行相应查看。不推荐直接使用数字,应使用宏名,因为不同操作系统信号编号可能不同,但名称一致。

返回值:

成功: 0 失败: -1


root用户可以发送信号给任何用户,普通用户无法向root发送信号。
普通用户无法向其他普通用户发送信号终止其进程。只能向自己创建的进程发送信号。




raise 函数

给当前进程发送指定信号(自己给自己发信号),等价于kill(getpid(
sig)

在这里插入图片描述

参数:

sig: 信号编号
返回值:
成功:0 失败:非0



alarm 函数

功能:

设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送(14)SIGALRM信号。进程收到该信号,默认动作终止。每个进程都有且只有唯一的一个定时器。
取消定时器alarm(0),返回旧闹钟余下秒数。

参数:

seconds:指定的时间,单位秒

返回值:

return 0 or 剩余的秒数

定时与进程的状态无关,就绪、运行、挂起(阻塞、暂停)、终止、僵尸.…..无论进程处于何种状态,alarm都会计时。

信号操作

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

necesse

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

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

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

打赏作者

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

抵扣说明:

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

余额充值