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

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

时间:2024-09-17 21:52:08浏览次数:11  
标签: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,里面是一个数组,下标是信号,里面的内容是信号处理函数。

信号的机制——信号处理函数的注册_系统调用

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

相关文章

  • php开启file_put_contents函数的支持
    file_put_contents 是PHP中的一个内置函数,用于将字符串写入到文件中。如果这个函数不可用,通常是因为PHP的运行环境配置问题,或者是文件系统的权限设置问题。这里有一些可能的原因和解决方案:原因分析文件权限问题:文件或文件夹的权限设置不正确,导致PHP脚本无法写入文件......
  • 帝国ECMS怎么去掉“选择注册会员类型”
    要去掉帝国ECMS(EmpireCMS)系统中的“选择注册会员类型”页面,可以根据不同的版本采取不同的方法。以下是适用于不同版本的解决方案:对于帝国CMS6.6版本:连接到服务器上的网站目录,找到 e/class/user.php 文件。下载该文件到本地,并用文本编辑器打开。在文件中找到 $changeregi......
  • 【高中数学/三角函数/判别式法】若正数a,b(a>b)满足1/(a+b)+1/(a-b)=1,则3a+2b的最小值
    【问题】若正数a,b(a>b)满足1/(a+b)+1/(a-b)=1,则3a+2b的最小值为?【出处】《解题卡壳怎么办--高中数学解题智慧剖析》P38页第一题首问余继光、苏德矿著 【解答】由1/(a+b)+1/(a-b)=1,展开后可得(a-1)^2-b^2=1可设a=1+1/cosθ,b=sinθ/cosθ代入3a+2b得f(θ)=3+3/cosθ+......
  • 【高中数学/三角函数/判别式法】设x>0,y>0,x+2y=5,则(x+1)(2y+1)/(xy)^0.5的最小值为?
    【问题】设x>0,y>0,x+2y=5,则(x+1)(2y+1)/(xy)^0.5的最小值为?【出处】《解题卡壳怎么办--高中数学解题智慧剖析》P38页第3题首问余继光、苏德矿著 【解答】由x+2y=5可设x=5cosθ^2,y=5sinθ^2/2代入目标式得(x+1)(2y+1)/(xy)^0.5=(5cosθ^2+1)(5sinθ^2+1)/5cosθsin......
  • 高等数学 2.5 函数的微分
    目录一、微分的定义二、微分的几何意义三、微分运算1、函数和、差、积、商的微分法则2、复合函数的微分法则四、微分在近似计算中的应用一、微分的定义定义设函数\(y=f(x)\)在某区间内有定义,\(x_0\)及\(x_0+\Deltax\)在这区间内,如果函数的增量\[\Deltay=f(x_0+......
  • C++模板函数实现类型推导
    C++模板函数实现类型推导以快读函数举例说明无法类型推导的情况template<typenameT>inlineTread(){Tx=0;intf=1;charch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar(......
  • Python使用starmap函数批量更新数据库
    在数据库操作中,有时候需要对多条记录进行批量更新操作,而这些记录的更新逻辑可能是相同的,只是参数不同。starmap函数可以更加高效地实现批量更新数据库的操作。importsqlite3fromitertoolsimportstarmap#连接数据库conn=sqlite3.connect('example.db')cursor=conn......
  • Python 之函数
    函数参数位置参数: defpower(x):默认参数: defpower(x,n=2): 默认参数必须指向不变对象!可变参数: defcalc(*numbers):关键字参数: defperson(name,age,**kw):命名关键字参数:defperson(name,age,*,city,job):参数组合:在Python中定义函数,可以用必选参数、默认参数......
  • pikachu靶场的代码审计,和一些危险函数
    对pikachu靶场进行代码审计,审计分析文件上传、命令执行漏洞,越权漏洞,sql注入,xxe漏洞文件上传client:并未对后缀进行判断,只对大小做了验证后端并未进行文件的类型校验,仅仅是生成了一个目录去保存上传的文件同时对文件的保存路径暴露MIMEType只对mime进行了验证,很容易绕过......
  • C++信奥老师解一本通题 1370:最小函数值(minval)
    ​【题目描述】有n个函数,分别为F1,F2,...,Fn。定义Fi(x)=Ai*x*x+Bi*x+Ci(x∈N∗)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的mm个(如有重复的要输出多个)。【输入】第一行输入两个正整数n和m。以下nn行每行三个正整数,其中第ii行的三个数分别位Ai、Bi和Ci输入数......