每日一模块-signal(代码片段)

sunxiuwen sunxiuwen     2022-12-01     242

关键词:

一、信号是什么,有什么作用?

1. 信号简介

连接Linux都知道,Linux以进程为单位来执行程序。我们可以将计算机看作一个大楼,内核(kernel)是大楼的管理员,进程是大楼的房客。每个进程拥有一个独立的房间(属于进程的内存空间),而每个房间都是不允许该进程之外的人进入。这样,每个进程都只专注于自己干的事情,而不考虑其他进程,同时也不让别的进程看到自己的房间内部。这对于每个进程来说是一种保护机制。(想像一下几百个进程总是要干涉对方,那会有多么混乱,或者几百个进程相互偷窥……)

然而,在一些情况,我们需要打破封闭的房间,以便和进程交流信息。比如说,内核发现有一个进程在砸墙(硬件错误),需要让进程意识到这样继续下去会毁了整个大楼。再比如说,我们想让多个进程之间合作。这样,我们就需要一定的通信方式。信号(signal)就是一种向进程传递信息的方式。我们可以将信号想象成大楼的管理员往房间的信箱里塞小纸条。随后进程取出小纸条,会根据纸条上的内容来采取一定的行动,比如灯坏了,提醒进程使用手电。(当然,也可以完全无视这张纸条,然而在失火这样紧急的状况下,无视信号不是个好的选择)。相对于其他的进程间通信方式(interprocess communication, 比如说pipe, shared memory)来说,信号所能传递的信息比较粗糙,只是一个整数。但正是由于传递的信息量少,信号也便于管理和使用。信号因此被经常地用于系统管理相关的任务,比如通知进程终结、中止或者恢复等等。

信号是由内核(kernel)管理的。信号的产生方式多种多样,它可以是内核自身产生的,比如出现硬件错误(比如出现分母为0的除法运算,或者出现segmentation fault),内核需要通知某一进程;也可以是其它进程产生的,发送给内核,再由内核传递给目标进程。内核中针对每一个进程都有一个表存储相关信息(房间的信箱)。当内核需要将信号传递给某个进程时,就在该进程相对应的表中的适当位置写入信号(塞入纸条),这样,就生成(generate)了信号。当该进程执行系统调用时,在系统调用完成后退出内核时,都会顺便查看信箱里的信息。如果有信号,进程会执行对应该信号的操作(signal action, 也叫做信号处理signal disposition),此时叫做执行(deliver)信号。从信号的生成到信号的传递的时间,信号处于等待(pending)状态(纸条还没有被查看)。我们同样可以设计程序,让其生成的进程阻塞(block)某些信号,也就是让这些信号始终处于等待的状态,直到进程取消阻塞(unblock)或者无视信号。

2. 常见的信号

信号所传递的每一个整数都被赋予了特殊的意义,并有一个信号名对应该整数。常见的信号有SIGINT, SIGQUIT, SIGCONT, SIGTSTP, SIGALRM等。这些都是信号的名字。你可以通过

$man 7 signal
NAME
       signal - 有效信号的清单

描述 (DESCRIPTION)
       下面 列出 Linux 支持的 信号. 某些 信号 依赖于 体系结构(architecture).

       首先, POSIX.1 描述了 下列 信号.

       信号         值      动作   说明
       ─────────────────────────────────────────────────────────────────────
       SIGHUP        1       A     在控制终端上是挂起信号, 或者控制进程结束
       SIGINT        2       A     从键盘输入的中断
       SIGQUIT       3       C     从键盘输入的退出
       SIGILL        4       C     无效硬件指令
       SIGABRT       6       C     非正常终止, 可能来自 abort(3)
       SIGFPE        8       C     浮点运算例外
       SIGKILL       9      AEF    杀死进程信号
       SIGSEGV      11       C     无效的内存引用
       SIGPIPE      13       A     管道中止: 写入无人读取的管道
       SIGALRM      14       A     来自 alarm(2) 的超时信号
       SIGTERM      15       A     终止信号
       SIGUSR1   30,10,16    A     用户定义的信号 1
       SIGUSR2   31,12,17    A     用户定义的信号 2
       SIGCHLD   20,17,18    B     子进程结束或停止
       SIGCONT   19,18,25          继续停止的进程
       SIGSTOP   17,19,23   DEF    停止进程
       SIGTSTP   18,20,24    D     终端上发出的停止信号
       SIGTTIN   21,21,26    D     后台进程试图从控制终端(tty)输入
       SIGTTOU   22,22,27    D     后台进程试图在控制终端(tty)输出

来查阅更多的信号。

上面几个信号中,

SIGINT 当键盘按下CTRL+C从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是中断 (INTERRUPT) 该进程。

SIGQUIT 当键盘按下CTRL+从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是退出 (QUIT) 该进程。

SIGTSTP 当键盘按下CTRL+Z从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是暂停 (STOP) 该进程。

SIGCONT 用于通知暂停的进程继续。

SIGALRM 起到定时器的作用,通常是程序在一定的时间之后才生成该信号。

3. 在shell中使用信号

下面我们实际应用一下信号。我们在shell中运行ping:

$ping localhost
#此时我们可以通过CTRL+Z来将SIGTSTP传递给该进程。shell中显示:
[1]+  已停止               ping localhost

我们使用$ps来查询ping进程的PID (PID是ping进程的房间号), 在我的机器中为27397

我们可以在shell中通过$kill命令来向某个进程发出信号:

$kill -SIGCONT 27397

来传递SIGCONT信号给ping进程。

4. 信号处理 (signal disposition)

在上面的例子中,所有的信号都采取了对应信号的默认操作。但这并不绝对。当进程决定执行信号的时候,有下面几种可能:

  1. 无视(ignore)信号,信号被清除,进程本身不采取任何特殊的操作

  2. 默认(default)操作。每个信号对应有一定的默认操作。比如上面SIGCONT用于继续进程。

  3. 自定义操作。也叫做获取 (catch) 信号。执行进程中预设的对应于该信号的操作。

进程会采取哪种操作,要根据该进程的程序设计。特别是获取信号的情况,程序往往会设置一些比较长而复杂的操作(通常将这些操作放到一个函数中)。

信号常常被用于系统管理,所以它的内容相当庞杂。深入了解信号,需要一定的Linux环境编程知识。

5. 结

信号机制; generate, deliver, pending, blocking

signal action/dispositon; ignore, default action, catch signal

$kill

二、python信号的使用signal

在了解了Linux的信号基础之 后,Python标准库中的signal包就很容易学习和理解。signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂 停并等待信号,以及定时发出SIGALRM等。要注意,signal包主要是针对UNIX平台(比如Linux, MAC OS),而Windows内核中由于对信号机制的支持不充分,所以在Windows上的Python不能发挥信号系统的功能。

信号(signal)-- 进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。

1. 定义信号名

signal包定义了各个信号名及其对应的整数,比如:

import signal

print(signal.SIGABRT)
print(signal.SIG_DFL)
# 结果
Signals.SIGABRT
Handlers.SIG_DFL
# Python所用的信号名与Linux一致,可以通过$ man 7 signal 查询

『牛角书』鸿蒙实现简单的每日新闻(代码片段)

(目录)Guide这是一篇讲解如何实现基于鸿蒙JS的简单的每日新闻。1.可滚动区域在许多场景中,页面会有一块区域是可滚动的,比如这样一个简单的每日新闻模块:上面的新闻类型是一块可横向滚动的区域,下方新闻列表是一块可... 查看详情

算法每日一题(代码片段)

文章目录题目描述利用回溯那就利用动态规划题目描述Youaregivenanintegerarraycoinsrepresentingcoinsofdifferentdenominationsandanintegeramountrepresentingatotalamountofmoney.Returnthenumberofcombinationsthatmakeupthatamount.Iftha 查看详情

信号signal(代码片段)

...统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers)。信号系统包含以下三要素:发送者-信号的发出方信号-信号本身接收者-信号的接受者Django内置了一整套信号,下面是一些比较常... 查看详情

每日一题741.摘樱桃(代码片段)

741.摘樱桃线性DPclassSolutionstaticintN=55,INF=Integer.MIN_VALUE;staticint[][][ 查看详情

每日一题927.三等分(代码片段)

927.三等分模拟题classSolutionpublicint[]threeEqualParts(int[]arr)//用于记录每个“1”所在arr中的位置(index)int[]record 查看详情

每日一博-instanceofvsisinstancevsisassignablefrom(代码片段)

文章目录PreisInstanceisAssignableFromPreoperatorinstanceof;methodClass.isInstance(Objectobj);methodClass.isAssignableFrom(Class<?>cls);isInstance/***Determinesifthespecified@codeObjectisassignme 查看详情

每日一博-instanceofvsisinstancevsisassignablefrom(代码片段)

文章目录PreisInstanceisAssignableFromPreoperatorinstanceof;methodClass.isInstance(Objectobj);methodClass.isAssignableFrom(Class<?>cls);isInstance/***Determinesifthespecified@codeObjectisassignme 查看详情

django信号signal(代码片段)

...信号系统可以允许一个或多个发送者(senders)将信号(signals)发送给一组接收者(receivers),此时接收者进行一些相关处理动作。信号系统包含以下三要素:信号:Signal对象发送者:信号发出方接收者:信号接收方Django内置了... 查看详情

每日一题676.实现一个魔法字典(代码片段)

676.实现一个魔法字典添加链接描述Trie+DFSclassMagicDictionaryintN=100*100,M=26,idx=0;int[] 查看详情

每日一练<4>(代码片段)

每日一练大家好呀!我是小笙,接下来分享下11-12月份每日一题的解题思路~1822.数组元素积的符号给定一个数组,将数组中的每个值乘积起来如果等于0则返回0;如果大于0则返回1;如果小于0则返回-1例子输入&#... 查看详情

每日一题1656.设计有序流(代码片段)

1656.设计有序流模拟题classOrderedStreamString[]s=newString[1010];intptr,newN;//构造一个能接收n个值的流,并将当前指针ptr设为1。publicOrderedStream 查看详情

leetcode9月每日一题(代码片段)

【LeetCode】9月每日一题9.1题目1475.商品折扣后的最终价格思路模拟即可代码functionfinalPrices(prices:number[]):number[]letlen:number=prices.lengthletres:number[]=newArray(len)for(leti=0;i<len-1;i++)letdiscou 查看详情

leetcode9月每日一题(代码片段)

【LeetCode】9月每日一题9.1题目1475.商品折扣后的最终价格思路模拟即可代码functionfinalPrices(prices:number[]):number[]letlen:number=prices.lengthletres:number[]=newArray(len)for(leti=0;i<len-1;i++)letdiscou 查看详情

每日一句(代码片段)

2020/2/18DAY1Mostresearchersreportedhavingprideintheirinstitutionsandpassionfortheirwork,butspokeofthehighpersonaltolloftheirenvironment.Manyacceptedthatpressureandlonghourscamewiththeterritory.Butresearcherssaidthatthesituationwasworseningandthatthenegativeaspectswerenolongeroffsetbyjobsecurityandt... 查看详情

每日一练<3>(代码片段)

每日一练大家好呀!我是小笙,接下来分享下10月份每日一题的解题思路~1441.用栈操作构建数组给你一个数组target和一个整数n。数组target是严格递增的,并且只包含1到n之间的数字从1遍历到n,如果在target数组中&#x... 查看详情

每日一题640.求解方程(代码片段)

640.求解方程把“-”替换成“±”,然后,先按“=”分割,再按“+”分割,再移项、合并同类项即可,注意,“x”和“-x”的特殊处理。classSolutionpublicStringsolveEquation(Stringequation)//把x移到左边,把其他移到右边String[]arr1=equation. 查看详情

笔试强训之每日一题(代码片段)

笔试强训之每日一题(八)文章目录笔试强训之每日一题(八)单词缩写题目描述输入描述输出描述题目代码URL化题目描述题目解析题目代码单词缩写题目描述在日常书面表达中,我们经常会碰到很长的单词,比如"localizatio... 查看详情

每日一题1282.用户分组(代码片段)

1282.用户分组哈希表模拟维护一张哈希表,key为人所在的组的大小,value为第i个人,当size等于key时,划分为1个组。使用ArrayList动态数组实现哈希表:classSolutionpublicList<List<Integer>>groupThePeople 查看详情