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

Linux 信号


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


目录

  • Linux 信号
  • 前言
    • 概述
    • 信号编号
      • 信号表
    • 信号要素
    • 信号的状态
      • 信号的产生
    • 阻塞信号集、未决信号集
    • 信号相关函数
      • kill 函数
      • raise 函数
      • alarm 函数
    • 信号操作


前言

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

信号的特点:

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

概述


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

Linux系统编程 ----信号详解_第1张图片

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


信号编号

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


kill -l 查看对应信号
Linux系统编程 ----信号详解_第2张图片

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


信号表


信号要素

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

man 7 singal 查看

Linux系统编程 ----信号详解_第3张图片

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


Action

Linux系统编程 ----信号详解_第4张图片

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 函数

给指定进程发送指定信号
Linux系统编程 ----信号详解_第5张图片

参数:
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)

Linux系统编程 ----信号详解_第6张图片

参数:

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



alarm 函数

功能:

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

参数:

seconds:指定的时间,单位秒

返回值:

return 0 or 剩余的秒数

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

信号操作

你可能感兴趣的:(Linux,linux,运维,C/C++,Java,编程语言)