【Linux信号】信号检测处理与捕捉

目录

进程什么时候检测处理信号?以及内核如何实现信号的捕捉?

sigaction

volatile


信号由操作系统发送给相应的进程,进程保存信号,最后再捕捉处理信号。

进程什么时候检测处理信号?以及内核如何实现信号的捕捉?

操作系统执行状态由内核态返回到用户态的时候,进行信号的检测和处理!

内核态和用户态是操作系统中两种不同的执行状态,限制不同程序的访问权限。由于系统调用是内核的数据,因此OS要切换到内核态(CPU内部的esc寄存器也会切换到内核态),两者配合这管理运行该程序。

上图是信号被检测处理和捕捉的示意图。

我们对于该示意图有如下分析:

如果信号的处理动作是用户自定义函数在信号递达时就调用这个函数这称为 捕捉信号 。由于信号处理函数的代码是在用户空间的处理过程比较复杂举例如下用户程序定义了 SIGQUIT 信号的处理函 数sighandler 当前正在执行main 函数 这时如果碰到系统调用(这里最常见)、中断或异常OS切换到内核态。在系统调用完毕后要返回用户态的 main 函数之前检查到有信号SIGQUIT 递达。内核决定返回用户态后不是恢复 main 函数的上下文继续执行而是执行 sighandler 函数 ,sighandler和 main 函数使用不同的堆栈空间 , 它们之间不存在调用和被调用的关系是两个独立的控制流程。 sighandler 函数返回后自动执行特殊的系统调用 sigreturn 再次进入内核态。如果没有新的信号要递达 , 这次再返回用户态就是恢复main 函数的上下文继续执行了。

sigaction

int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
头文件:<signal.h>

功能:sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回-1。

参数:signo 是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传出该信号原来的处理动作。act和oact指向sigaction结构体。

struct sigaction结构体:

volatile

今天我们站在信号的角度重新理解一下该关键字:
#include <stdio.h>
#include <signal.h>
int flag = 0;
void handler(int sig)
{
 printf("chage flag 0 to 1\n");
 flag = 1;//在优化条件下, flag变量可能被直接优化到CPU内的寄存器中
}
int main()
{
 signal(2, handler);
 while(!flag);
 printf("process quit normal\n");
 return 0;
}
标准情况下,键入 CTRL-C ,2号信号被捕捉,执行自定义动作,修改 flag=1 , while 条件不满足,退出循环,进程退出。

makefile里的形成可执行文件时:gcc -o signal signal.c -O1/2/3,优化flag变量

volatile 作用:保持内存的可见性,告知编译器,被该关键字修饰的变量,不允许被优化,对该变量的任何操作,都必须在真实的内存中进行操作。
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值