首页 > 其他分享 >信号的机制——信号处理函数的注册

信号的机制——信号处理函数的注册

时间:2023-11-17 22:33:36浏览次数:38  
标签:SIGRTMAX 注册 函数 信号处理 调用 信号 signal SIGRTMIN

在 Linux 操作系统中,为了响应各种各样的事件,也是定义了非常多的信号。我们可以通过 kill -l 命令,查看所有的信号。

# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

这些信号都是什么作用呢?我们可以通过 man 7 signal 命令查看,里面会有一个列表。

Signal     Value     Action   Comment
──────────────────────────────────────────────────────────────────────
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction


SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
……

就像应急预案里面给出的一样,每个信号都有一个唯一的 ID,还有遇到这个信号的时候的默认操作。

一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。

1.执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 Term,就是终止进程的意思。Core 的意思是 Core Dump,也即终止进程后,通过 Core Dump 将当前进程的运行状态保存在文件里面,方便程序员事后进行分析问题在哪里。

2.捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。

3.忽略信号。当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP,它们用于在任何时候中断或结束某一进程。

信号处理最常见的流程。这个过程主要是分成两步,第一步是注册信号处理函数。第二步是发送信号。

如果我们不想让某个信号执行默认操作,一种方法就是对特定的信号注册相应的信号处理函数,设置信号处理方式的是 signal 函数。

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

这其实就是定义一个方法,并且将这个方法和某个信号关联起来。当这个进程遇到这个信号的时候,就执行这个方法。

如果我们在 Linux 下面执行 man signal 的话,会发现 Linux 不建议我们直接用这个方法,而是改用 sigaction。定义如下:

int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);

另外一个设置就是 SA_NOMASK。我们通过 __sigemptyset,将 sa_mask 设置为空。这样的设置表示在这个信号处理函数执行过程中,如果再有其他信号,哪怕相同的信号到来的时候,这个信号处理函数会被中断。如果一个信号处理函数真的被其他信号中断,其实问题也不大,因为当处理完了其他的信号处理函数后,还会回来接着处理这个信号处理函数的,但是对于相同的信号就有点尴尬了,这就需要这个信号处理函数写得比较有技巧了。

还有一个设置就是设置了 SA_INTERRUPT,清除了 SA_RESTART。这是什么意思呢?我们知道,信号的到来时间是不可预期的,有可能程序正在调用某个漫长的系统调用的时候(你可以在一台 Linux 机器上运行 man 7 signal 命令,在这里找 Interruption of system calls and library functions by signal handlers 的部分,里面说得非常详细),这个时候一个信号来了,会中断这个系统调用,去执行信号处理函数,那执行完了以后呢?系统调用怎么办呢?

这时候有两种处理方法,一种就是 SA_INTERRUPT,也即系统调用被中断了,就不再重试这个系统调用了,而是直接返回一个 -EINTR 常量,告诉调用方,这个系统调用被信号中断了,但是怎么处理你看着办。如果是这样的话,调用方可以根据自己的逻辑,重新调用或者直接返回,这会使得我们的代码非常复杂,在所有系统调用的返回值判断里面,都要特殊判断一下这个值。

另外一种处理方法是 SA_RESTART。这个时候系统调用会被自动重新启动,不需要调用方自己写代码。当然也可能存在问题,例如从终端读入一个字符,这个时候用户在终端输入一个'a'字符,在处理'a'字符的时候被信号中断了,等信号处理完毕,再次读入一个字符的时候,如果用户不再输入,就停在那里了,需要用户再次输入同一个字符。

因此,建议你使用 sigaction 函数,根据自己的需要定制参数。

如何通过 API 注册一个信号处理函数,整个过程如下图所示。

  • 在用户程序里面,有两个函数可以调用,一个是 signal,一个是 sigaction,推荐使用 sigaction。
  • 用户程序调用的是 Glibc 里面的函数,signal 调用的是 __sysv_signal,里面默认设置了一些参数,使得 signal 的功能受到了限制,sigaction 调用的是 __sigaction,参数用户可以任意设定。
  • 无论是 __sysv_signal 还是 __sigaction,调用的都是统一的一个系统调用 rt_sigaction。
  • 在内核中,rt_sigaction 调用的是 do_sigaction 设置信号处理函数。在每一个进程的 task_struct 里面,都有一个 sighand 指向 struct sighand_struct,里面是一个数组,下标是信号,里面的内容是信号处理函数。

信号的机制——信号处理函数的注册_信号处理

信号的机制——信号处理函数的注册_信号处理_02

标签:SIGRTMAX,注册,函数,信号处理,调用,信号,signal,SIGRTMIN
From: https://blog.51cto.com/key3feng/8455516

相关文章

  • MATLAB/Simulink中调用C语言实现的传递函数
    1.引言在变流器控制中,通常采用C语言实现传递函数,且通常写成独立的C文件,本文简要介绍如何在MATLAB/Simulink中调用这些C文件。在本文中,采用C语言实现了一阶低通滤波器、二阶低通滤波器、滑动平均滤波器,具体代码见附录。同时需要安装C编译工具链,参考《UsingGCCwithMinGW》。2......
  • 重写Java中Arrays数组工具类提供的sort()排序函数中的比较器类Comparator的compare()
    排序方法是我们日常开发或者写功能函数,或者实现算法时,常调用的方法。有时甚至,开发人员自己还要写一写排序算法。今天,我们来修改Java官方提供的Arrays工具类中的静态排序sort()方法。反问一下,为什么要重写呢?官方提供的还不够你用?回答:确实不够用,官方默认是对数字,特别是sort比较的......
  • 似然函数的作用
    似然函数是统计学和机器学习中一个关键的概念,它在参数估计和模型选择等方面发挥着重要作用。下面详细解释似然函数的定义和作用:1.定义:似然函数通常用L(θ∣X)表示,其中θ是模型参数,X是观测到的数据。似然函数描述了在给定一组参数θ的条件下,观测到数据X的概率。2.作......
  • 梯度消失和梯度爆炸——从本质上说残差、LSTM遗忘门(依赖cell state)解决思路都是一样的
    在深度学习中,梯度消失和梯度爆炸是两个常见的问题。梯度消失是指在进行反向传播时,梯度会随着层数的增加而指数级地减小,直到几乎消失,导致深层的神经网络参数无法有效更新。这主要是因为使用了像sigmoid和tanh这样的激活函数,它们在输入值较大或较小的情况下,梯度值接近于0。    梯......
  • 使用C语言Beep()函数演奏歌曲
    曲子是大佬王宗贤的《孔雀之舞》,网上没有找到五线谱,只有简谱,而且曲子速度不明确。通过相关演奏音乐的可大体得知,因为连音较多,至10个小节处为24秒,所以每个小节是2.4秒,因为是2/4拍,每个小节是2拍,所以每半个拍子对应的时长是0.6秒,对应的是一个八分音符的音长,600毫秒在函数中用变量f控......
  • 体验函数计算 FC 3.0,写测评赢取索尼头戴式耳机
    11月1日云栖大会,**函数计算3.0全新升级,相对函数计算2.0,3.0版本突出易用性、高弹性,并且可以和更多阿里云服务无缝集成。**业内首发神龙ServerlessGPU架构,冷启动大幅优化,全链路调度延时降低80%,函数执行性能波动率降低70%;作为事件驱动的全托管计算服务,足够轻量灵活,让用户以更少的......
  • vue~全局插件和全局方法的注册
    本文介绍如何在vue中定义插件,注册插件和使用插件插件目录/src/plugins插件入口文件/src/plugins/index.jsimportcachefrom'./cache'importmodalfrom'./modal'//安装默认插件,在main.js中引入,通过Vue.use()使用它,因为index.js里使用exportdefault导出,所有在main.js里导入......
  • 体验函数计算 FC 3
    11月1日云栖大会,函数计算3.0全新升级,相对函数计算2.0,3.0版本突出易用性、高弹性,并且可以和更多阿里云服务无缝集成。业内首发神龙ServerlessGPU架构,冷启动大幅优化,全链路调度延时降低80%,函数执行性能波动率降低70%;作为事件驱动的全托管计算服务,足够轻量灵活,让用户以更少的代......
  • 彻底理解回调函数
    彻底理解回调函数的实现原理原创 码农的荒岛求生 码农的荒岛求生 2023-11-1708:11 发表于北京大家好,我是小风哥,有很多同学问能不能发下之前的文章,后续我会找一些之前阅读量不错的发下,本文首发于2021年10月,以下是正文。其实之前小风哥写过关于回调函数原理的文章,在这里《1......
  • 学习笔记426—keras中to_categorical函数解析
    keras中to_categorical函数解析1.to_categorical的功能简单来说,to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示。其表现为将原有的类别向量转换为独热编码的形式。先上代码看一下效果:fromkeras.utils.np_utilsimport*#类别向量定义b=[0,1,2,3,4,5,6,7,8]......