linux通信机制signal()函数详解

2023-10-29

  我们来谈一谈signal()函数的作用。

  linux系统提供了signal()和sigaction()两个函数来改变对于信号的处理方法。其中signal()是一个基于sigaction()系统调用的glibc库函数,其行为在不同的linux操作系统存在差异,对于可移植性有要求的程序不能使用signal()函数。


1.什么是信号?

  信号(signal)是一种进程间通信机制,它给应用程序提供一种异步的软件中断,使应用程序有机会接受其他程序活终端发送的命令(即信号)。应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉。进程收到一个信号后,会检查对该信号的处理机制。如果是SIG_IGN,就忽略该信号;如果是SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。

  信号的本质是异步。异步一这个词,听着高端大气上档次,又让人云山雾绕,其则不然。其实我们想想,我们这个世界是异步的,每个人干事儿,并不总是A->B->C->D这种。比如我在网上买了东西,我其实并不知道快递几时能到。我可能在公司里面,在喝水,在回邮件,在查bug,在写代码,突然收到了快递小哥的电话,注意这就是信号的delivery。由于快递的到来,我不得不停下我手头的活儿,去签收快递。这就是传说中的典型的异步。我不知道快递小哥几时给我电话,但是我收到电话就去签收,这是我的信号处理函数。更高级一点,如果我在参加重要的会议,我可能需要屏蔽快递小哥的电话(假如我知道其电话),这已经是linux下信号的高级应用(sigprocmask)了。
    信号是一种机制,是在软件层次对中断机制的一种模拟,内核让某进程意识到某特殊事情发生了。强迫进程去执行相应的信号处理函数。至于信号的来源可能来自硬件如按下键盘或者硬件故障(如ctrl+c发送SIGINT),可能来自其他进程(kill,sigqueue),可能来自自己进程(raise)。 
    信号的本质是一种进程间的通信,一个进程可以向另一个进程发送信号。


2.函数原型

在signal.h头文件中,它的声明如下:


#include <signal.h>
void (*signal(int sig_num, void (*handler)(int))(int);

成功则返回该信号以前的处理配置, 出错则返回SIG_ERR.

让我们一步步地从外向内去理解:

前面说到,signal函数返回值是函数指针,这个指针指向的函数名如下:

    void (*fp) (int)      //pointer to a function 

对应到上面的函数原型,这里的 fp 相当于

  signal (int sig_num, void (*handler)(int))  

如此一来,函数就易于理解地多了。

这里面的机制是这样的,内外有两层函数。内层是void(*handle)(int)  signal(int sig_num,void(*handler)(int)),也就是说signal函数接收了一个函数指针作为参数,又把这个函数作为了返回值,传给fp,fp再去调用这个函数。

这个函数有两个参数,第一个参数sig_num指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。第二个参数,是一个无返回值、接受一个int形参的函数指针。函数的第二个参数可以有三种选择,第一种是我们自己定义的信号处理函数,第二种是传入SIG_DFL 表示将之前signal所改变的信号处理方式还原,第三种是传入SIG_IGN,表示处理方式为忽略该信号,内核会直接将信号丢弃,不会传递到进程。

signal函数的返回值同样是一个无返回值、接受一个int形参的函数指针。当signal()函数成功执行时,返回值是执行signal函数之前的sig信号的处理函数的指针,如果失败,则返回SIG_ERR(-1)。


3.参数详解

以下是参数sig_num

Signal Description
SIGABRT 由调用abort函数产生,进程非正常退出
SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS 某种特定的硬件异常,通常由内存访问引起
SIGCANCEL 由Solaris Thread Library内部使用,通常不会使用
SIGCHLD 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT 当被stop的进程恢复运行的时候,自动发送
SIGEMT 和实现相关的硬件异常
SIGFPE 数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE Solaris专用,Hiberate或者Suspended时候发送
SIGHUP 发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL 非法指令异常
SIGINFO BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO 异步IO事件
SIGIOT 实现相关的硬件异常,一般对应SIGABRT
SIGKILL 无法处理和忽略。中止某个进程
SIGLWP 由Solaris Thread Libray内部使用
SIGPIPE 在reader中止之后写Pipe的时候发送
SIGPOLL 当某个事件发送给Pollable Device的时候发送
SIGPROF Setitimer指定的Profiling Interval Timer所产生
SIGPWR 和系统相关。和UPS相关。
SIGQUIT 输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV 非法内存访问
SIGSTKFLT Linux专用,数学协处理器的栈异常
SIGSTOP 中止进程。无法处理和忽略。
SIGSYS 非法系统调用
SIGTERM 请求中止进程,kill命令缺省发送
SIGTHAW Solaris专用,从Suspend恢复时候发送
SIGTRAP 实现相关的硬件异常。一般是调试异常
SIGTSTP Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN 当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU 当Background Group的进程尝试写Terminal的时候发送
SIGURG 当out-of-band data接收的时候可能发送
SIGUSR1 用户自定义signal 1
SIGUSR2 用户自定义signal 2
SIGVTALRM setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING Solaris Thread Library内部实现专用
SIGWINCH 当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU 当CPU时间限制超时的时候
SIGXFSZ 进程超过文件大小限制
SIGXRES Solaris专用,进程超过资源限制的时候发送

这些都是定义好的宏,有的时候也会用数字做参数:

SIGHUP 1 A 终端挂起或者控制进程终止

SIGINT 2 A 键盘中断(如break键被按下)

SIGQUIT 3 C 键盘的退出键被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)发出的退出指令

SIGFPE 8 C 浮点异常

SIGKILL 9 AEF Kill信号

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 控制终端(tty)上按下停止键

SIGTTIN 21,21,26 D 后台进程企图从控制终端读

SIGTTOU 22,22,27 D 后台进程企图从控制终端写




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux通信机制signal()函数详解 的相关文章

  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • 如何在特定 systemd 服务重新启动时触发自定义脚本运行

    我想知道如何安排自定义脚本在重新启动服务时运行 我的用例是 每当重新启动 Tomcat 服务时 我都必须运行多个命令 我想知道是否有一种方法可以编写脚本并安排它在重新启动 Tomcat 服务时运行 我已将 tomcat 脚本设置为 syst
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • 让 MongoDB 在 Linux 上监听远程连接

    我已在 Windows 本地计算机上 上成功安装 MongoDB 作为服务 但现在我想将 MongoDb 移动到单独的服务器 所以我将 tarball 解压到网络上的虚拟服务器 运行 Linux 当我从本地计算机使用 PuTTY 连接到服务
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • 如何制作和应用SVN补丁?

    我想制作一个SVN类型的补丁文件httpd conf这样我就可以轻松地将其应用到其他主机上 If I do cd root diff Naur etc httpd conf httpd conf original etc httpd con
  • 并行运行 make 时出错

    考虑以下制作 all a b a echo a exit 1 b echo b start sleep 1 echo b end 当运行它时make j2我收到以下输出 echo a echo b start a exit 1 b star
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • 修改linux下的路径

    虽然我认为我已经接近 Linux 专业人士 但显然我仍然是一个初学者 当我登录服务器时 我需要使用最新版本的R 统计软件 R 安装在 2 个地方 当我运行以下命令时 which R I get usr bin R 进而 R version
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • Linux 中的无缓冲 I/O

    我正在写入大量的数据 这些数据数周内都不会再次读取 由于我的程序运行 机器上的可用内存量 显示为 空闲 或 顶部 很快下降 我的内存量应用程序使用量不会增加 其他进程使用的内存量也不会增加 这让我相信内存正在被文件系统缓存消耗 因为我不打算
  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • GLIBCXX_3.4.26 未找到在 BeagleBone 上运行交叉编译的程序

    我有以下程序 include
  • 如何使用 bash 锁定文件

    我有一个任务从远程服务器同步目录 rsync av email protected cdn cgi l email protection srv data srv data 为了使其定期运行并避免脚本 reEnter 问题 我使用 rsyn
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • 如何在 shell 脚本中并行运行多个实例以提高时间效率[重复]

    这个问题在这里已经有答案了 我正在使用 shell 脚本 它读取 16000 行的输入文件 运行该脚本需要8个多小时 我需要减少它 所以我将其划分为 8 个实例并读取数据 其中我使用 for 循环迭代 8 个文件 并在其中使用 while
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数

随机推荐

  • STC89C52系列单片机内部资源——中断系统

    中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的 中断功能的存在 很大程度上提高了单片机处理外部或者内部事件的能力 它也是单片机最重要的功能之一 是我们学习单片机必须要掌握 首先介绍单片机中断技术的优点 解决了快速主机与慢速I
  • FastGPT 接入飞书(不用写一行代码)

    FastGPT V4 版本已经发布 可以通过 Flow 可视化进行工作流编排 从而实现复杂的问答场景 例如联网谷歌搜索 操作数据库等等 功能非常强大 还没用过的同学赶紧去试试吧 飞书相比同类产品算是体验非常好的办公工具了 我司也是废了很大的
  • 操作系统学习(三)基本分段存储管理方式

    一 分段的定义 进程的地址空间按照自身的逻辑关系划分为若干段 例如 主程序 两个子程序 栈和一段数据 把进程分成5段 每段从0进行编址 段间要求连续 段内不要求 二 段表 1 分段系统的逻辑地址结构由段号 段名 和段内地址 段内偏移量 组成
  • uni-app中自定义动态底部tabbar(附示例源码)

    UNIAPP 自带的原生导航尽管流畅度非常好 但是在具体项目中有的时候需要动态设置以及特殊样式的 底部菜单 这个时候就需要自己去写一个自定义的底部tabbar 项目地址 fr uni app 1 比如需要特殊的图标 多出来一部分的 2 根据
  • 每日30条知识点-软件设计师知识点笔记

    立即寻址最快 寄存器寻址次之 直接寻址最慢 RISC 精简指令集计算机 特点 指令数量少 寻址方式少 长度固定 格式种类少 只提供load store指令访问存储器 以硬布线逻辑控制为主 单周期指令执行 系统总线用于主存以及外设部件连接 R
  • 数据结构和算法--树

    数据结构和算法是一种思想 理解了思想就是忘记了代码也能找回原来的记忆 二叉搜索树 二叉树 每个结点只存储一个关键字 等于则命中 小于走左结点 大于走右结点 AVL树 每个节点的左子树和右子树的高度最多差1的二叉搜索树 B B 树 多路搜索树
  • C++(26)——对象被优化以后才是最高效的C++编程

    对象应用优化 我们都知道 C语言和C 在程序执行中 都是通过调用一系列的函数来实现的 并且 很多时候 编译器会帮助我们做一系列的事情 比如 在编译类的成员方法的时候 编译器默认添加 this 指针 以此来确定是哪一个对象调用了该成员方法 得
  • C#上位机串口控制12864显示

    实现的效果 上面是用Proteus仿真的 对了如果自己想用proteus仿真需要安装下面这个软件 再看一下实物显示效果 先做上位机部分 为了程序一启动就把电脑上能用的串口号显示在下拉框中 private void Form1 Load ob
  • android使用Glide加载RelativeLayout、LinearLayout等背景图片

    转载请注明出处 http blog csdn net ym4189 article details 78712256 Glide框架大家应该都很熟悉 我们可以使用Glide加载网络图片 加载gif图片 使用简单 一般情况下我们都是使用Gli
  • 解决 adbd cannot run as root in production builds 问题

    这学期的一个android实验遇到的问题 经过借鉴多位大佬的文章已经解决 我的情况是android studio 不能很好的连接goole浏览器 所以不能下载其他版本 看到其他方法 https blog csdn net w69033324
  • 如何解决(变量或函数)重复定义的问题?

    错误提示 Objects light 1 axf Error L6200E Symbol gpio init multiply defined by gpio o and main o Not enough information to l
  • mongoose 实现DBRef查找所有子类信息

    产品表 var Mongoose require mongoose var Schema Mongoose Schema var Product new Schema image type String description type S
  • 【highlight】highlight 动态添加代码,样式失效

    在使用highlight 的时候 发现效果不错 然而当我用jQuery改变内容时 酷炫的高亮效果没了 原来hljs initHighlightingOnLoad 初始化的时候只会对其渲染一次 查阅资料发现 解决方案 code code 使用
  • s3 实现图片上传并返回图片路径

    一般做图片上传的的业务时我们接收的都是 MultipartFile 类型的文件 但是s3提供的图片上传只支持file 类型的文件上传 所以需要我先把 MultipartFile 转换为 file MultipartFile 转换为file
  • 递归树形结构的多级分类数据封装

    在日常开发中 我们经常需要查询一些树形结构的多级分类数据 如 多级菜单 商品三级分类 企业组织架构等等 我们以商品三级分类为例 大部分情况下 在同一张数据表中 无论是一级商品还是三级商品 每一条商品信息独占一行空间 通过 层级 字段 标明该
  • 金先生的 NutUI3 初体验

    冬日清晨 客服小王第一个来到了公司 还没顾得上脱下厚厚的羽绒服 桌上的电话就响了起来 您好 这里是京东客服 请问有什么可以帮到您的么 电话那头很嘈杂 呼啸的北风让来电人的声音很难被听清 而唯一可以被弄懂的就是对方一直在声嘶力竭反复强调的 开
  • 人脸相似度对比

    由清晰的人脸照转化出的像素值矩阵 应当设计出什么样的函数 f x 转化为特征值呢 这个问题的答案依赖于分类问题 即 先不谈特征值 首先如何把照片集合按人正确地分类 这里就要先谈谈机器学习 机器学习认为可以从有限的训练集样本中把算法很好地泛化
  • Sql Server 锁知识及锁应用

    转 sql server锁知识及锁应用 胡杰的专栏 CSDN博客sql server锁 lock 知识及锁应用一 关于锁的基础知识二 锁的分析及应用系列三 SQL Server 锁机制 悲观锁 乐观锁 实测解析四 SQL Server 中W
  • android车载行业前景,车载 Android 系统快来了,但前景可能并不乐观

    行业内相关主机厂 供应商已经习惯了利用移动版 Android 系统的开源性 进行框架层面的定制化改造 但是 车载 Android 系统为了保证满足车规应用 显然不会像移动版那样有很大的灵活定制性 特别是当谷歌开始把手伸向更底层的车辆控制系统
  • linux通信机制signal()函数详解

    我们来谈一谈signal 函数的作用 linux系统提供了signal 和sigaction 两个函数来改变对于信号的处理方法 其中signal 是一个基于sigaction 系统调用的glibc库函数 其行为在不同的linux操作系统存在