操作系统:信号

article/2025/8/15 4:18:43

文章目录

  • 一 信号概念
    • 1. 信号简介
    • 2. 信号/事件 产生方式
    • 3. 信号处理方式
  • 二 信号实现
    • 1. 不可靠信号
    • 2. 可靠与不可靠信号类型
    • 3. 被中断的系统调用
    • 4. 信号函数
      • 4.1 信号发送函数 kill/raise
      • 4.2 定时发送信号函数 alarm
      • 4.3 信号捕获等待函数 pause
    • 5. 信号集
      • 5.1 信号集来由
      • 5.2 信号集函数
    • 6 进程与信号控制
      • 6.1 sigprocmask
      • 6.2 sigpending
      • 6.3 sigaction
      • 6.4 sigsetjmp 与 siglongjmp
      • 6.5 sigsuspend

一 信号概念

1. 信号简介

进程可以两耳不问窗外事,一心一意演自己的剧本。
但是进程是依附于操作系统上实现的应用,进程需要被管理。其它进程或者操作系统可能会随时来本进程家门口敲门拜访,这就是信号!

信号有两个特点:
第一,信号是异步的,理解为异步的事件;
第二,进程对外来事件的处理是异步的!

2. 信号/事件 产生方式

  • 用户按键:用户使用某种特殊字符递送给终端,产生一个信号(事件)递送给进程
  • 硬件故障:进程执行错误,比如访问一个无效内存地址,这时候先由硬件报告给内核,再由内核把事件递送给进程
  • kill函数或者命令:通过函数把需要的事件直接递送给进程

3. 信号处理方式

当我们把信号形象的理解为异步事件后,分析问题会更加清晰
信号/事件 发生时,谁去处理事件,怎么处理呢?是有进程自己处理吗,还是操作系统处理?
现代操作系统给出的答案是,有些事件进程可以指定要如何处理。但是一些特殊的事件过于严重,操作系统决定默认处理方式!

这样,信号处理就分为三种形式:
第一,捕获:进程调用自己的函数处理事件
第二,忽略:事件发生,进程与操作系统都不做理会
第三,默认:事件发生,操作系统的默认操作

二 信号实现

1. 不可靠信号

不可靠指:信号发生了,但是它可能会丢失;

下面图文说明了一个信号常见的处理过程:
第一步,信号产生:终端按键/指令故障/kill函数事件发生后,事件会被记录在进程描述结构当中
第二步,信号处理:如果信号未被阻塞,信号处理方式选择为忽略/默认/捕获中的一种
第三步,信号未决:这一步和第二步互斥,如果信号被阻塞,信号暂时将得不到处理

sigpending 函数用于查询被阻塞并且pending状态的信号(已经发生的信号)
sigprocmask 用于查询当前哪些信号(未必发生过)需要被阻塞
在这里插入图片描述

那么我们继续回到最初的问题:信号不可靠指的是什么?
假如我们已经有一个SIGCHLD信号在signal pending的状态中,这个时候从其他进程递送过来好多个SIGCHLD信号,按照道理这些信号需要记录在进程表结构当中------但是,进程表相关结构可能不支持链表,它记录不下这么多信号,于是后面的信号可能覆盖原来的信号(最终只得到一个信号)
最后N个信号只保留了一个!丢失了N-1个,也就是不可靠的概念
与之相对,有的信号在发生时,会在进程表中进行排队,这样一个信号也不会丢失,这样的信号叫做可靠信号
在这里插入图片描述

2. 可靠与不可靠信号类型

使用kill -l命令可以得到系统支持的信号类型
其中 1~31项为不可靠信号, 34~64为可靠信号
在这里插入图片描述

3. 被中断的系统调用

与I/O相关的接口通常会引起进程被挂起/睡眠
正常情况下,IO操作完成后,操作系统将唤醒进程,进程获取了自己期望的结果
但是也有异常,进程因为IO操作被挂起后,可能因为信号被唤醒!同时,不能操作系统可能实现可能也不同!

读者可以参考《UNIX高级环境编程》一书中相关章节
附表;部分平台上系统调用被中断的情况
在这里插入图片描述

4. 信号函数

4.1 信号发送函数 kill/raise

kill

   #include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);

功能:
pid == 0,信号发送给当前进程所属进程组
pid > 0,信号发送给指定的进程(用户权限满足情况下)
pid < 0,信号发送给指定进程组:进程组ID ==|pid|(用户权限满足情况下)
pid == -1,信号发送给所有有权限发送信号的进程

raise

信号发送给进程自身,同时raise函数支持多线程模型,这是POSIX规定的#include <signal.h>int raise(int sig);

4.2 定时发送信号函数 alarm

alarm
#include <unistd.h>

   unsigned int alarm(unsigned int seconds);

功能:
进程休眠指定时间,超时时产生一个SIGALRM信号,此信号默认终止进程
另外,信号产生到信号处理程序被调用不是立刻完成的,需要额外时间开销

4.3 信号捕获等待函数 pause

pause
#include <unistd.h>

   int pause(void);

功能:
进程休眠,并且只在捕获一个信号并从信号处理程序返回时,pause才会返回

5. 信号集

5.1 信号集来由

早期操作系统上信号不超过32个,因此信号使用一个int整型表示,每一个bit对应一个信号

现代操作系统,信号种类越来越多,信号不再使用一个int表示,定义了新的类型sigset_t-------信号集

函数集数据结构处理 函数原型

       #include <signal.h>int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);/*sigemptyset() initializes the signal set given by set to empty, with all signals excluded from the set.sigfillset() initializes set to full, including all signals.sigaddset() and sigdelset() add and delete respectively signal signum from set.sigismember() tests whether signum is a member of set.*/

5.2 信号集函数

#include <iostream>
using namespace std;extern "C"
{#include <signal.h>
}/*int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);
*/void check_sig(sigset_t const *set)
{if(NULL == set)return;for(int cnt = 1;cnt <= SIGRTMAX;cnt++){/*注意:把错误的signum值传递给函数,会返回-1,即错误*/int res = sigismember(set,cnt);if( res == -1){cout << "err during sigismember" << endl;return;}else if(1 == res){cout << "Signal " << cnt << " is a member of sigset" << endl;}}
}
int main()
{sigset_t set;/*没有信号*/sigemptyset(&set);check_sig(&set);cout << "--------------" << endl;/*系统支持的所有信号都包含在内 [1,31],[33,64]*/sigfillset(&set);check_sig(&set);cout << "---------SIGQUIT = " << SIGQUIT << endl;cout << "-----Del signal----SIGQUIT = " << endl;	/*删除一个信号 SIGQUIT*/sigdelset(&set,SIGQUIT);check_sig(&set);cout << "-----------add SIGQUIT-----------" << endl;/*添加回来被删掉的信号 SIGQUIT*/sigaddset(&set,SIGQUIT);check_sig(&set);return 0;
}

6 进程与信号控制

6.1 sigprocmask

获取或者设置进程对信号集的阻塞控制

#include <iostream>
using namespace std;extern "C"
{#include <signal.h>
}/*int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);// how = {SIG_BLOCK | SIG_UNBLOCK | SIG_SETMASK}int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
*/void check_sig(sigset_t const *set)
{if(NULL == set)return;for(int cnt = 1;cnt <= SIGRTMAX;cnt++){/**/int res = sigismember(set,cnt);if( res == -1){cout << "err during sigismember" << endl;return;}else if(1 == res){cout << "Signal " << cnt << " is a member of sigset" << endl;}}
}int main()
{sigset_t set;/*默认所有信号 非阻塞*/cout << "read default blocked status" << endl << endl;sigprocmask(0,NULL,&set);check_sig(&set);/*尝试阻塞所有信号:结果信号都被阻塞,SIGKILL(9)和SIGSTP(19)除外(这两个信号不允许阻塞)*/cout << "set filled signals to blocked status" << endl << endl;sigfillset(&set);if(-1 == sigprocmask(SIG_SETMASK,&set,NULL)){cout << "err while calling sigprocmask" << endl;return -1;}sigprocmask(0,NULL,&set);check_sig(&set);/*尝试去除SIGCHLD阻塞:结果成功*/cout << "unblockSIGCHLD signal" << endl << endl;sigemptyset(&set);sigaddset(&set,SIGCHLD);if(-1 == sigprocmask(SIG_UNBLOCK,&set,NULL)){cout << "err while calling sigprocmask" << endl;return -1;}sigprocmask(0,NULL,&set);check_sig(&set);return 0;
}

6.2 sigpending

检查未决的信号,未决信号条件:
1、信号被阻塞
2、信号处理方式为默认方式或者捕获方式
3、 信号已经发生

#include <iostream>
using namespace std;extern "C"
{#include <signal.h>
}/*int sigemptyset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);// how = {SIG_BLOCK | SIG_UNBLOCK | SIG_SETMASK}int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);int sigpending(sigset_t *set);typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);
*/void check_sig(sigset_t const *set)
{if(NULL == set)return;for(int cnt = 1;cnt <= SIGRTMAX;cnt++){/**/int res = sigismember(set,cnt);if( res == -1){cout << "err during sigismember" << endl;return;}else if(1 == res){cout << "Signal " << cnt << " is a member of sigset" << endl;}}
}void sig_quit_handler(int signum)
{/*do nothing*/}int main()
{/*SIGQUIT信号处理方式设置为捕获*/signal(SIGQUIT,sig_quit_handler);/*阻塞SIGQUIT信号*/sigset_t set;sigemptyset(&set);sigaddset(&set,SIGQUIT);sigprocmask(SIG_BLOCK,&set,NULL);/*产生SIGQUIT信号*/raise(SIGQUIT);cout << "raise is called" << endl;/*获取pending 阻塞的信号*/sigpending(&set);/*检查返回信号,打印出3 ---即 SIGQUIT/check_sig(&set);return 0;
}

6.3 sigaction

功能:
1、注册信号处理函数 以及 信号处理函数执行时,信号屏蔽/阻塞控制
2、挂起的系统调用被信号中断后:是返回"被中断状态"还是系统调用重启
3、其它信号处理细节控制
4、拓展:信号底层函数,可以用来实现signal函数…

  • 代码略

6.4 sigsetjmp 与 siglongjmp

函数原型: 提供了非局部跳转时,信号屏蔽字的控制功能
#include <setjmp.h>

   int setjmp(jmp_buf env);int sigsetjmp(sigjmp_buf env, int savesigs);void siglongjmp(sigjmp_buf env, int val);
// An highlighted block
var foo = 'bar';

6.5 sigsuspend

功能:
使用mask临时替换现有信号屏蔽字,然后等待任意信号被捕获,信号处理程序执行并返回后,信号屏蔽字被恢复为原来默认值

   #include <signal.h>int sigsuspend(const sigset_t *mask);

http://chatgpt.dhexx.cn/article/NrGrKt70.shtml

相关文章

信号与系统—信号的描述与分类

信号的描述和分类 信号的描述 函数表示 信号通常是时间变量t的函数&#xff0c;所以对于某一类信号可以用时间函数来表示&#xff0c;如 c ( u ) { 0 &#xff0c; t < 0 e − t τ &#xff0c; t ≥ 0 c(u)\begin{cases} 0&#xff0c;t<0\\ e^{-\frac{t}{\tau}}&…

操作系统——信号

信号的概念 信号的产生 信号的注册 信号的注销 自定义信号处理方式 信号的捕捉流程 信号阻塞 信号的概念&#xff1a; 1.信号是一个软件中断 2.信号的种类&#xff1a; kill -l命令的时候&#xff0c;我们会看到62种信号 1~31 &#xff1a; 非可靠信号&#xff0c; 信号有可能…

信号与系统(典型信号)

1.信号的描述与信号的分类 1.1基于信号维度分类 一维信号&#xff08;声音&#xff09;、二维信号&#xff08;图像&#xff09;、三维信号&#xff08;视频&#xff09;、四维信号&#xff08;VR中看到的信号&#xff09;、…N维。 信号与系统中只讨论一维信号 1.2一维信号…

信号与系统1-概述

目录&#xff1a; 一、概述 1、信号与系统概念 1&#xff09;信号 2&#xff09;系统 2、信号的描述、分类与典型信号 1&#xff09;描述方式 2&#xff09;信号的分类 &#xff08;1&#xff09;确定信号/随机信号 &#xff08;2&#xff09;周期信号/非周期信号 &#xff0…

【信号与系统】(四)信号与系统概述——系统的概念及分类

文章目录 第一章 信号与系统概述1.4 系统的概念及分类1.4.1 系统定义与典型系统举例1.4.1.1 系统定义1.4.1.2 系统模型1.4.1.3 系统的状态1.4.1.4 典型系统举例 1.4.2 系统分类1.4.2.1 连续系统与离散系统1.4.2.2 动态系统与即时系统1.4.2.3 单输入单输出系统与多输入多输出系统…

信号系统 | 信号的概念与常用信号

信号的本质是函数&#xff0c;因此信号处理方法具有普适性&#xff0c;应用领域非常广泛。本篇介绍信号的基本概念以及一些典型的信号&#xff0c;主要参考奥本海姆的经典教材《信号与系统》&#xff0c;微信搜索公众号PurePlay&#xff0c;后台回复Oppenheim即可获取中文PDF。…

【信号与系统】(二)信号与系统概述——基本信号

文章目录 第一章 信号与系统概述1.2基本信号1.2.1 阶跃函数1.2.2 冲激函数1.2.3 冲激函数的广义函数定义1.2.4 冲激函数的取样性质1.2.4.1 f ( t ) f(t) f(t)乘以 δ ( t ) δ(t) δ(t)1.2.4.2 f ( t ) f(t) f(t)乘以 δ ( t − a ) δ(t-a) δ(t−a) 1.2.5 冲激函数的导数1.…

【信号与系统|吴大正】1:信号与系统概述

信号与系统概述 写在前面&#xff1a; 自己也感觉最近基础类课程开了好多坑…因为发现未来研究领域跟数字信号处理也脱离不了关系&#xff0c;打算从《信号系统与线性分析》开始慢慢往后补&#xff1b;大二下期的时候学习过了这门课&#xff0c;但其实现在回过头来知识也不剩多…

城市轨道交通信号系统学习笔记(二)信号系统的组成

信号系统的组成 一、列车自动控制&#xff08;ATC&#xff09;系统 二、车联段联锁设备 城市轨道交通信号系统通常由列车自动控制&#xff08;Automatic Train Control&#xff0c;ATC&#xff09;系统和车辆段/停车场信号控制系统两大部分组成。用于列车进路控制、列车间隔控制…

信号与系统——基本概念

目录 基础知识 信号与系统&#xff08;Signals and Systems&#xff09; 信号 信号的定义 信号的分类 系统 基础知识 信号理论主要包括&#xff1a;信号分析&#xff0c;信号传输&#xff0c;信号综合&#xff1b;系统理论主要包括&#xff1a;系统分析和系统综合 信号…

MATLAB信号与系统

目录 1.基本信号的MATLAB表示1.1.指数信号1.2.指数序列1.3.正弦型信号1.4.抽样函数Sa(t)1.5.矩形脉冲函数1.6.三角波脉冲信号1.7.单位采样序列1.8.单位阶跃序列 2.信号基本运算的MATLAB实现2.1.信号的尺度变换、翻转、时移&#xff08;平移&#xff09;2.2.信号的相加与相乘2.3…

《信号与系统学习笔记》—信号与系统(三)

注&#xff1a;本博客是基于奥本海姆《信号与系统》第二版编写&#xff0c;主要是为了自己学习的复习与加深。 一、单位冲激与单位阶跃函数 一&#xff09;、离散时间单位脉冲和单位阶跃序列 1、单位脉冲 最简单的离散时间信号之一就是单位脉冲&#xff0c;或称单位样本&…

【信号与系统】

1、信号、信息与消息的差别&#xff1f; 消息&#xff1a;语音、文字、图像、图像等都是消息。 信息&#xff1a;消息中包含的有效或有意义的内容。 信号&#xff1a;信息的必须转换为电信号&#xff0c;才能在通信系统中传输&#xff0c;因此&#xff0c;信号是消息的载体&am…

操作系统 —— 信号

文章目录 1. 信号的感性理解2. 发送信号的方式2.1 键盘发送信号2.2 进程异常产生信号2.3 调用系统函数发送信号2.4 触发软件条件&#xff0c;发送信号 3. 信号的控制3.1 先来学习几个概念3.2 信号发送的本质3.3 信号的阻塞3.4 信号的捕捉初识3.5 信号捕捉的本质3.6 信号集操作函…

信号与系统--信号以及系统的介绍(一)

文章目录 一、绪论1、概述2、信号及其分类3、系统及其分类 总结 一、绪论 1、概述 课程内容 两大对象 &#xff1a; 信号、系统 三种分析方法&#xff1a;时域分析方法、频域分析方法、复频域分析方法 三大变换&#xff1a;傅里叶变换、拉普拉斯变换、Z变换 我们会用这些方法去…

第一章:绪论与信号系统概述

在学习通信原理之前&#xff0c;我们先回顾一下通信原理的数学理论基础——信号与系统讲了些什么&#xff0c;有哪些难以理解的问题。 下面开始第一章&#xff08;以吴大正主编的第五版教材为依据&#xff0c;以下简称《信号》&#xff09; PS:这是我复习知识时整理的&#x…

我彻底服了,大牛讲解信号与系统(通俗易懂)

我彻底服了,大牛讲解信号与系统(通俗易懂) (2015-10-13 21:22:36) 转载▼ 分类&#xff1a; 电力电子技术 第一课什么是卷积卷积有什么用什么是傅利叶变换什么是拉普拉斯变换 引子 很多朋友和我一样&#xff0c;工科电子类专业&#xff0c;学了一堆信号方面的课&#xff0c;…

3.16(杨神)

分组背包搞树形dp多叉转二叉 原理存储进行输出方案 分组背包搞树形dp 多叉转二叉 原理 左儿子&#xff0c;右兄弟 存储 for(int i1;i<n;i){xxread();yyread();vvread();//xx为yy的son。 b[xx]s[yy];s[yy]xx;value[i]vv;} 进行 不选 f[i][j]f[rr][j] 选 f[i][j]f[ll][…

一些社会运行的底层规律,和你的利益息息相关

点击上方蓝字关注「中产之路」 任志强是房地产行业为数不多敢讲真话的大佬&#xff0c;早期因为坚持讲真话&#xff0c;孜孜不倦&#xff0c;开启民智&#xff0c;观点尚未被大众认可&#xff0c;一度成为全民公敌&#xff0c;也有了“任大炮”的称号。退休后的他&#xff0c;依…

数据结构—共享栈

数据结构-栈(Ⅳ) 共享栈 利用栈底位置相对不变的特性&#xff0c;可让两个顺序栈共享一个一维数组空间&#xff0c;将两个栈的栈底分别设置在共享空间的两端&#xff0c;两个栈顶向共享空间的中间延伸。 共享栈是为了更有效地利用存储空间&#xff0c;两个栈的空间相互调节&a…