操作系统-信号管理

一、信号介绍

中断:当进程接收到消息后中止当前正在执行的任务,转而执行其它任务,等待其它任务执行完毕后再返回继续执行。这种执行模式称为中断,分为硬件中断和软件中断两种

信号

  • 信号是UNIX、类UNIX以及其他POSIX兼容的系统中,为了完成不同进程之间通讯的一种方式。是一种软中断,是一种异步处理机制,用于提醒进程某个事件发生了,可能要去处理。
  • 当一个信号发送给一个进程,操作系统就会中断该进程的正常控制流程,如果中断前预先设置过如何处理该信号(绑定过该信号的信号处理函数),那么中断后会执行该函数,执行完返回中断点继续执行,否则就按信号的默认处理方式进行

执行 kill -l 查看当前系统可以产生的所有信号

信号 解释 产生条件 默认动作
SIGHUP(1) 连接断开信号 如果终端接口检测一个连接断开,则将此信号发送给与该终端相关的控制进程(会话首进程) 终止
SIGINT(2) 终端中断符信号 用户按中断键Ctrl+C,产生此信号,并送至前台进程组的所有进程 终止
SIGQUIT(3) 终端退出符信号 用户按退出键Ctrl+,产生此信号,并送至前台进程组的所有进程 终止+core
SIGILL(4) 非法硬件指令信号 进程执行了一条非法硬件指令 终止+core
SIGTRAP(5) 硬件故障信号 指示一个实现定义的硬件故障。常用于调试 终止+core
SIGABRT(6) 异常终止信号 调用abort函数,产生此信号 终止+core
SIGBUS(7) 总线错误信号 指示一个实现定义的硬件故障,常用于内存故障 终止+core
SIGFPE(8) 算术异常信号 表示一个算术运算异常,例如除以0、浮点溢出等 终止+core
SIGKILL(9) 终止信号 不能被捕获或忽略。常用于杀死进程 终止
SIGUSR1(10) 用户定义信号 用户定义信号,用于应用程序 终止
SIGSEGV(11) 段错误信号 试图访问未分配的内存,或向没有写权限的内存写入数据 终止+core
SIGUSR2(12) 用户定义信号 用户定义信号,用于应用程序 终止
SIGPIPE(13) 管道异常信号 写管道时读进程已终止,或写SOCK_STREAM类型套接字时连接已断开,均产生此信号 终止
SIGALRM(14) 闹钟信号 alarm函数设置的计时器到期,或以setitimer函数设置的间隔时间到期,均产生此信号 终止
SIGTERM(15) 终止信号 kill命令发送的系统默认终止信号 终止
SIGSTKFLT(16) 数协器栈故障信号 表示数学协处理器发生栈故障 终止
SIGCHLD(17) 子进程状态改变信号 在一个进程终止或停止时,将此信号发送给其父进程 忽略
SIGCONT(18) 使停止的进程继续 向处于停止状态的进程发送此信号,令其继续运行 继续/忽略
SIGSTOP(19) 停止信号 不能被捕获或忽略。停止一个进程 停止进程
SIGTSTP(20) 终端停止符信号 用户按停止键Ctrl+Z,产生此信号,并送至前台进程组的所有进程 停止进程
SIGTTIN(21) 后台读控制终端信号 后台进程组中的进程试图读其控制终端,产生此信号 停止
SIGTTOU(22) 后台写控制终端信号 后台进程组中的进程试图写其控制终端,产生此信号 停止
SIGURG(23) 紧急情况信号 有紧急情况发生,或从网络上接收到带外数据,产生此信号 忽略
SIGXCPU(24) 超过CPU限制信号 进程超过了其软CPU时间限制,产生此信号 终止+core
SIGXFSZ(25) 超过文件长度限制信号 进程超过了其软文件长度限制,产生此信号 终止+core
SIGVTALRM(26) 虚拟闹钟信号 setitimer函数设置的虚拟间隔时间到期,产生此信号 终止
SIGPROF(27) 虚拟梗概闹钟信号 setitimer函数设置的虚拟梗概统计间隔时间到期,产生此信号 终止
SIGWINCH(28) 终端窗口大小改变信号 ioctl函数更改窗口大小,产生此信号 忽略
SIGIO(29) 异步I/O信号 指示一个异步I/O事件 终止
SIGPWR(30) 电源失效信号 电源失效,产生此信号 终止
SIGSYS(31) 非法系统调用异常 指示一个无效的系统调用 终止+core

不可靠信号与可靠信号

不可靠信号

  • 建立在早期信号处理机制上的信号被称为不可靠信号(1-31)
  • 非实时信号,不支持排队机制,可能会丢失信号,同一个信号产生多次,进程可能只收到一次
  • 当进程收到这类信号,执行了第一次用户设置的信号处理函数后,会还原会默认的处理方式。

可靠信号

  • 位于(34-64)的信号是可靠信号
  • 实时信号,支持排队机制,信号只要产生就必定会被处理,因此不会丢失

信号的来源

  • 硬件异常:由硬件设备产生的信号,例如除零、非法访问内存、总线错误、未定义指令
  • 软件异常:命令kill\函数产生信号

信号处理的默认动作

  • 忽略
  • 终止进程
  • 终止并产生core文件
  • 捕获并处理

二、捕获信号

//	信号处理函数的格式
typedef void (*sighandler_t)(int);

/**
 * 功能: 向内核注册一个信号和它的信号处理函数,相当于捕获该信号(绑定信号)
 * @signum: 信号码(可以写整数值也可以用宏名)
*/
sighandler_t signal(int signum, sighandler_t handler);
  • 在某些UNIX系统中,通过signal注册信号处理函数后,只有一次有效,后面会变回默认处理方式,为了在这种系统中得到持久的信号绑定,可以在信号处理函数的末尾再次通过signal重新注册一次
  • 可以通过命令 kill 信号码 进程号 给该进程发送信号
  • 普通用户只能给自己的进程发送信号,只有root用户可以给任何进程发送信号
  • 当信号处理完信号处理函数后是会回到产生信号的代码位置继续执行,如果我们捕获并处理的是段错误\除零这种信号,就会产生死循环,因为这些错误并没有因为捕获了信号就消失,而是一直存在并产生信号,正确做法是在他们的信号处理函数中进行数据保存然后直接结束程序。exit()

注意:9和19号信号不能被忽略也不能被不能被捕获

三、发送信号的方式

键盘:
  • 给当前终端控制下的活跃进程发送信号
    • Ctrl+c Ctrl+\ Ctrl+z fg
命令:
kill <-信号码> 进程号
killall <-信号码> 进程名 
# 给所有的同名的进程发送信号
事件:
  • 当程序执行了某种非法操作,被操作系统发现了,操作系统会给进程发送对应的信号,例如段错误、除零、总线错误、错误指令等。
函数:
/**
 * 功能: 给指定的进程发送信号
 * @pid: 给进程号为pid的进程发送
 *	pid > 0		给pid号进程发送信号sig
 *	pid = 0		给同组的所有进程发送信号sig
 *	pid = -1	给所有进程发送信号sig,前提是有向该进程发送信号的权限
 *	pid < -1    向进程组id等于pid的绝对值的所有进程发送信号
*/
int kill(pid_t pid, int sig);
	
/**
 * 功能: 给调用进程自己发送信号
*/
int raise(int sig);

/**
 * 功能: 给调用进程自己发送信号SIGABRT(6)
*/
void abort(void);

/**
 * 功能: 让内核在seconds秒后,向调用进程发送SIGALRM(14)信号
 * 返回值: 上一次alarm剩余的时间,
 * 如果是正常走完时间返回0,如果时间还没走完,又再次调用alarm后,会覆盖之前的时间重新计时,并不会产生多个闹钟信号
*/
unsigned int alarm(unsigned int seconds);

四、暂停和休眠

/**
 * 功能: 让调用进程进入暂停态执行,进入睡眠状态,直到有信号终止进程或者有信号被捕获,
 * 会唤醒并执行信号处理函数,继续后面的执行流程。类似于不限时的sleep
 * 返回值: 要么一直睡眠不返回,睡醒返回-1
*/
int pause(void);

/**
 * 功能: 让调用进程睡眠seconds秒,除非有信号终止进程或者有信号被捕获,也会唤醒
 * 返回值: 剩余的睡眠秒数
*/
unsigned int sleep(unsigned int seconds);

/**
 * 功能: 让调用进程睡眠usec微秒,除非有信号终止进程或者有信号被捕获,也会唤醒
 * 返回值: 剩余的睡眠秒数
*/
int usleep(useconds_t usec)

五、信号集与信号屏蔽

信号集

  • 是一种专门用于存储多个信号的数据类型 sigset_t
  • 该类型占128字节,每个字节代表了一种信号的有或无

操作信号集的相关函数

/**
 * 功能: 将信号集set中的所有信号置零 清空信号集
*/
int sigemptyset(sigset_t *set);

/**
 * 功能: 把信号集set中所有信号置1 
*/
int sigfillset(sigset_t *set);

/**
 * 功能: 将信号集set中的信号signum置1
*/
int sigaddset(sigset_t *set, int signum);

/**
 * 功能: 将信号集set中的信号signum置0
*/
int sigdelset(sigset_t *set, int signum);

/**
 * 功能: 测试信号集中是否存在signum信号
 * 返回值: 存在返回1,不存在返回0 非法信号返回-1
*/
int sigismember(const sigset_t *set, int signum);
信号的递送与未决:
  • 当信号产生后,系统内核会在其内部维护的进程表中,给响应信号的进程设置一个对应的标志位,着整个过程称为信号的递送
  • 在信号产生到完成递送之间会存在一段时间间隔,处于这个时间间隔的信号状态是“未决”
信号屏蔽:
  • 每个进程都有用一个信号掩码(signal mask,就是一个信号集),其中存在的信号是需要被该进程屏蔽的信号
  • 让需要屏蔽的信号处于“未决状态”,当可以接收信号时,让其退出未决状态,完成递送
  • 当执行一些特殊的且不想被干扰中断的操作时,例如:更新数据库敏感操作,此时可以把信号放入信号屏蔽集中,等操作完成后,再从信号屏蔽集中删除,继续处理信号,能保证敏感操作的安全性

信号屏蔽集的操作函数:

/**
 * 功能: 修改当前进程的信号掩码(屏蔽集)
 * @how: 修改信号掩码的方式:
 *	SIG_BLOCK  		将set中的信号加入到信号掩码中
 *	SIG_UNBLOCK		从信号掩码中把set中的信号删除
 *  SIG_SETMASK		把set中的信号替换掉信号掩码的所有信号
 * @set: 信号集 用于设置
 * @oldsel: 信号集 用于获取旧信号集 NULL则不获取
*/
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
posted @   sleeeeeping  阅读(96)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
  1. 1 吹梦到西洲 恋恋故人难,黄诗扶,妖扬
  2. 2 敢归云间宿 三无Marblue
敢归云间宿 - 三无Marblue
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

敢归云间宿 - 三无Marblue

词:怀袖

曲:KBShinya

编曲:向往

策划:杨颜

监制:似雨若离RainJaded/杨颜

吉他:大牛

混音:三无Marblue

和声:雾敛

母带:张锦亮

映像:似雨若离RainJaded

美术:阿尼鸭Any-a/乙配/雨谷/今风/米可/Eluan

题字:长安

酒 泼去群山眉头

酒 泼去群山眉头

月 悬在人世沧流

空杯如行舟 浪荡醉梦里走

心 生自混沌尽头

心 生自混沌尽头

对 天地自斟自酬

诗随我 遍历春秋

行流水 走笔形生意动

见珠玉 淙淙落纸成诵

拾得浮名有几声 云深处 却空空

耳畔丝竹 清商如雾

谈笑间 却是心兵穷途

飞觞醉月无归宿 便是孤独

不如就化身为风

卷狂沙 侵天幕

吹醒那 泉下望乡 的战骨

昨日边关犹灯火

眼前血海翻覆

千万人跌落青史 隔世号呼

于是沸血重剑共赴

斩以雷霆之怒

肩背相抵破阵开路

万古同歌哭

纵他春风不度 悲欢蚀骨

此去宁作吾

挣过命途 才敢写荣枯

望 云际群龙回首

望 云际群龙回首

任 飘蓬争逐身后

叹冥顽之俦 好景尽付恩仇

收 江声随酒入喉

收 江声随酒入喉

来 提笔御风同游

不觉已 换了春秋

真亦假 泼墨腾烟沉陆

有还无 蝶影纷堕幻目

我与天地周旋久

写尽梦 便成梦

夜雨浇熄 往事残烛

生死间 谁尽兴谁辜负

管他醒来归何处 心生万物

也曾对电光火雨

抛酒樽 镇天枢

护住了 人间多少 朝与暮

烧尽了阴云冥府

烧尽了阴云冥府

且看星斗尽出

浩荡荡尘埃野马 忘怀命数

于是信步鸿蒙之轻

也领苍生之重

与诗与剑颠倒与共

沉眠斜阳中

纵他世事汹涌 万类争渡

此去宁作吾

醉得糊涂 才梦得清楚

潮水 带着叹息轻抚

潮水 带着叹息轻抚

像光阴 漫过大地上幽微草木

有情世 见众生明灭往复

天生自在 何必回顾

晦暗中双掌一拊

立此身 照前路

与某个 阔别的我 决胜负

渺渺兮身外无物

无喜无悲无怖

不过是大梦一场 各自沉浮

于是纵横万相穷通

也守心底灵通

合眼识得星沉地动

也岿然不动

敢令岁月乌有 逍遥长驻

敢归云间宿

遥祝远行人 有道不孤

点击右上角即可分享
微信分享提示