什么是信号

在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。

当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,如果进程定义了对信号的处理,此时,程序将进入捕获到的信号对应的处理函数,否则执行默认的处理函数。

Linux中信号的介绍

在Linux系统共定义了64种信号,分为两大类:实时信号非实时信号,1-31为非实时,32-64种为实时信号。

  • 非实时信号: 也称为不可靠信号,为早期Linux所支持的信号,不支持排队,信号可能会丢失, 比如发送多次相同的信号, 进程只能收到一次. 信号值取值区间为1~31;
  • 实时信号: 也称为可靠信号,支持排队, 信号不会丢失, 发多少次, 就可以收到多少次. 信号值取值区间为32~64

Linux操作系统中,在终端上执行 kill -l 便可看到系统定义的所有信号

信号表

POSIX.1-1990标准信号

此表参考自:POSIX信号

信号 动作 说明
SIGHUP 1 Term 终端控制进程结束(终端连接断开)
SIGINT 2 Term 用户发送INTR字符(Ctrl+C)触发
SIGQUIT 3 Core 用户发送QUIT字符(Ctrl+/)触发
SIGILL 4 Core 非法指令(程序错误、试图执行数据段、栈溢出等)
SIGABRT 6 Core 调用abort函数触发
SIGFPE 8 Core 算术运行错误(浮点运算错误、除数为零等)
SIGKILL 9 Term 无条件结束程序(不能被捕获、阻塞或忽略)
SIGSEGV 11 Core 无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作)
SIGPIPE 13 Term 消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作)
SIGALRM 14 Term 时钟定时信号
SIGTERM 15 Term 结束程序(可以被捕获、阻塞或忽略)
SIGUSR1 30,10,16 Term 用户保留
SIGUSR2 31,12,17 Term 用户保留
SIGCHLD 20,17,18 Ign 子进程结束(由父进程接收)
SIGCONT 19,18,25 Cont 继续执行已经停止的进程(不能被阻塞)
SIGSTOP 17,19,23 Stop 停止进程(不能被捕获、阻塞或忽略)
SIGTSTP 18,20,24 Stop 停止进程(可以被捕获、阻塞或忽略)
SIGTTIN 21,21,26 Stop 后台程序从终端中读取数据时触发
SIGTTOU 22,22,27 Stop 后台程序向终端中写数据时触发

更多的信号说明请查阅man7

此表的操作为每个信号的默认配置,如下所示

动作 说明
Term 默认操作是,终止进程。
Ign 默认操作是,忽略信号。
Core 默认操作是,终止该进程并核心转储
Stop 默认操作是,停止进程。
Cont 默认操作是,如果当前已停止,则继续该进程。

信号的产生

​信号是事件发生时对进程的通知机制。信号中断与硬件中断的相似之处在于打断了程序执行的正常流程。

信号事件的来源分为软件信号和硬件信号:

  • 硬件信号: 用户输入:比如在终端上按下组合键ctrl+C,产生SIGINT信号;硬件异常:CPU检测到内存非法访问等异常,通知内核生成相应信号,并发送给发生事件的进程;
  • 软件信号: 通过系统调用: 如,发送signal信号:killraise等。

发送的信号

  • Ctrl-C 发送 INT signal (SIGINT),通常导致进程结束
  • Ctrl-Z 发送 TSTP signal (SIGTSTP); 通常导致进程挂起(suspend)
  • Ctrl-\ 发送 QUIT signal (SIGQUIT); 通常导致进程结束 和 dump core.

信号的处理

内核处理进程收到的signal是在当前进程的上下文,故进程必须是Running状态。当进程唤醒或者调度后获取CPU,则会从内核态转到用户态时检测是否有signal等待处理,处理完,进程会把相应的未决信号从链表中去掉。

signal信号处理时机: 内核 ==> 信号处理 ==> 用户

  1. 内核态:在内核态,signal信号不起作用;
  2. signal信号处理: 在用户态,signal所有未被屏蔽的信号都处理完毕;当屏蔽信号,取消屏蔽时,会在下一次内核转用户态的过程中执行;

信号处理方式

进程对信号的处理方式有3种:

  • 默认 接收到信号后按默认的行为处理该信号。 这种方式为多数应用采取的处理方式。
  • 自定义处理 用自定义的信号处理函数来执行特定的动作
  • 忽略忽略信号 接收到信号后不做任何反应。

对信号的处理动作:

  • Term: 中止进程
  • Ign: 忽略信号
  • Core: 中止进程并保存内存信息
  • Stop: 停止进程
  • Cont: 继续运行进程

Linux信号命令

kill

kill命令用来终止指定的进程, 对于一个后台进程就须用kill命令来终止,我们就需要先使用ps/pidof/pstree/top等工具获取进程PID,然后使用kill命令来杀掉该进程。

命令格式

kill[参数] [进程id]

命令参数

-l 信号,若果不加信号的编号参数,则使用“-l”参数会列出全部的信号名称

-a 当处理当前进程时,不限制命令名和进程号的对应关系

-p 指定kill 命令只打印相关进程的进程号,而不发送任何信号

-s 指定发送信号

-u 指定用户

killall

Linux系统中的killall用于杀死指定名字的进程(kill processes by name)。我们可以使用kill命令杀死指定进程PID的进程,如果要找到我们需要杀死的进程,我们还需要在之前使用ps等命令再配合grep来查找进程,而killall把这两个过程合二为一,是一个很好用的命令。

命令格式

killall[参数] [进程名]

命令参数

-I 忽略小写

-a 当处理当前进程时,不限制命令名和进程号的对应关系

-i 交互模式,杀死进程前先询问用户

-s 发送指定的信号

-w 等待进程死亡

-e 要求匹配进程名称

PKILL

pkillkillall 使用方法类似,用于杀死指定名称的进程

Go语言中的Signal的使用

在Go语言中,处理信号仅需要3个步骤即可完成对信号的处理

  • 信号的接收: signalChan := make(chan os.Signal,1)
  • 信号的监听捕获: signal.Notify(signalChan)
  • 信号的触发: signal := <-signalChan

注意事项:

  • SIGKILL kill -9SIGSTOP kill -19 信号可能不会被Notify方法捕获,因此无法处理这些信号。
  • 如果在Notify方法中没有指定信号作为参数,那么该方法将捕获所有的信号。

在Go语言中的Signal的处理

在某些场景下,如,在大量并发及,批量处理未完成时,此时需要在Go程序中处理Signal信号,比如收到SIGTERM信号后优雅的关闭程序。

实例:在一个计算场景下,有5个goroutine在处理业务,当收到 kill -15时计算完成后退出程序, kill -4不做处理。

package main

import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
) var wg sync.WaitGroup func exitProcess() {
fmt.Println("等待进程完成")
wg.Wait()
fmt.Println("进程退出")
} func process(n int) {
i := n
for {
fmt.Println("process", n, ":", i)
if i > 100 {
break
}
time.Sleep(time.Second)
i++
}
fmt.Println("process", n, "finnshed")
defer wg.Done()
} func main() {
signals := make(chan os.Signal, 1)
done := make(chan bool, 1) signal.Notify(signals, syscall.SIGILL, syscall.SIGTERM) go func() {
for signal := range signals {
switch signal {
case syscall.SIGTERM, syscall.SIGQUIT:
fmt.Println("kill -15 进程退出")
exitProcess()
case syscall.SIGILL:
fmt.Println("kill -4")
}
}
done <- true
}() wg.Add(5)
for n := 0; n < 10; n++ {
go process(n)
} fmt.Println("waiting signal...")
wg.Wait()
fmt.Println("exiting")
}

收到kill -4 信号打印kill -4

收到kill -15 信号后,带程序处理完成后退出

Go进程间通讯

Linux信号与golang中的捕获处理的更多相关文章

  1. Linux信号

    信号本质上就是一个软件中断,它既可以作为两个进程间的通信的方式, 更重要的是, 信号可以终止一个正常程序的执行, 通常被用于处理意外情况 ,* 信号是异步的, 也就是进程并不知道信号何时会到达 $ki ...

  2. Linux 信号捕捉

    pause函数 pause函数挂起调用它的进程,直到有任何消息到达. 调用进程必须有能力处理送达的信号,否则信号的默认部署就会发生. int pause(void); 只有进程捕获到一个信号的时候pa ...

  3. 僵尸进程学习 & 进程状态列表 & Linux信号学习

    参考这篇文章: http://www.mike.org.cn/articles/treatment-of-zombie-processes-under-linux/ 在Linux进程的状态中,僵尸进程 ...

  4. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  5. [置顶] Linux信号相关笔记

    最近又温习了一遍Linux中的信号知识,发现有很多东西以前没有注意到,就通过这篇博客记录一下,巩固一下知识点. 一,信号基础: 信号是什么?为了回答这个问题,首先要从异常说起,这里的异常不是指c++/ ...

  6. linux 信号列表和基本作用

    我们运行如下命令,可看到Linux支持的信号列表: $ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7 ...

  7. Linux信号列表

    我们运行如下命令,可看到Linux支持的信号列表: ~$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL5) SIGTRAP 6) SIGABRT 7) ...

  8. Golang中的信号处理

    信号类型 个平台的信号定义或许有些不同.下面列出了POSIX中定义的信号. Linux 使用34-64信号用作实时系统中. 命令 man 7 signal 提供了官方的信号介绍. 在POSIX.1-1 ...

  9. Linux信号实践(2) --信号分类

    信号分类 不可靠信号 Linux信号机制基本上是从UNIX系统中继承过来的.早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号 ...

随机推荐

  1. python中zip函数的使用

    zip(*iterables) zip可以将多个可迭代对象组合成一个迭代器对象,通过迭代取值,可以得到n个长度为m的元组.其中n为长度最短可迭代对象的元素个数,m为可迭代对象的个数.并且每个元组的第i ...

  2. CVPR2021| 继SE,CBAM后的一种新的注意力机制Coordinate Attention

    前言: 最近几年,注意力机制用来提升模型性能有比较好的表现,大家都用得很舒服.本文将介绍一种新提出的坐标注意力机制,这种机制解决了SE,CBAM上存在的一些问题,产生了更好的效果,而使用与SE,CBA ...

  3. Redis解读(2):Redis的Java客户端

    Redis的Java客户端 Redis不仅使用命令客户端来操作,而且可以使用程序客户端操作,其实配置和实现起来也非常容易. 现在基本上主流的语言都有客户端支持,比如Java.C.C#.C++.php. ...

  4. OO UNIT 2 个人总结

    第二单元面向对象作业--性感电梯在线吃人 Part 1:单部可捎带电梯 多线程设计策略 本次电梯仅仅只有一部运行,因此,在多线程的设计中难度不大,并且,只需采用一对一的生产者-消费者模型即可解决问题. ...

  5. PAT B1033 旧键盘上的几个键又毁坏了,于是在输入一段文字时,对应得的字符就不会出现。

    题中可用的字母包括大小写(给出的坏键的字母,全为大写),数字,"_" "," "." "-" "+" ...

  6. MySQL数据库高级一:架构介绍

    两天半就可以 严禁使用 精通 在简历上 了解的越多,越比他人有优势 linux的mysql需要使用中文字符集那么就要修改配置文件 1.mysql的linux版 安装和卸载不说了 2.逻辑架构 总体概况 ...

  7. 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像制作fedora27-18

    自动化kolla-ansible部署ubuntu20.04+openstack-victoria之镜像制作fedora27-18 欢迎加QQ群:1026880196 进行交流学习   制作OpenSt ...

  8. 为Github的README.md生成目录的小工具

    1 概述 因为Github的README.md文件[TOC]不生效,因此封装了一个别人已封装好的JAR包供大家使用. 2 使用方法 用Java做的,只需要JDK11以上的环境: java -jar t ...

  9. Josephus问题的queue解法

    问题描述 Josephus问题是一个非常古老的问题.它的范型描述为N个人(0到N-1)围成一圈报数,报道M的人会被剔除,直到最后一个人. 要求找出最后一个人的位置或这N个人被剔除的顺序. 解决思路 我 ...

  10. php 日志处理工具 SeasLog 的使用

    首先附上seaslog github地址: https://github.com/Neeke/SeasLog/blob/master/README_zh.md php官方文档地址: https://w ...