当前位置: 首页 > news >正文

Linux信号——信号的处理(3)

信号是什么时候被处理?

进程从内核态,切换到用户态的时候,信号会被检测处理。
内核态:操作系统的状态,权限级别高
用户态:你自己的状态

内核态和用户态

进程地址空间第三次
所谓的系统调用本质其实是一堆函数指针数组。
1.我们使用系统调用或者访问系统数据,其实还是在我们进程的地址空间内进行跳转的。

2.进程无论如何切换,总能找到OS
我们访问OS,本质是通过我的进程的地址空间的[3,4]GB来访问的。
在这里插入图片描述

3.操作系统是如何运行的
信号技术本来就是通过软件的方式,来模拟的硬件中断
OS的周期时钟中断:非常高的频率,非常短的时间,给CPU发送中断——CPU不断进程处理中断。
操作系统是一个死循环,不断在接受外部的其他硬件中断。

4.操作系统不相信任何用户
必须要能区分当前用户的运行模式,所以就有了用户态和内核态。

信号是如何被处理?

在这里插入图片描述

捕捉信号还有其他方式吗?

#include <signal.h>

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

参数说明
signum: 要操作的信号编号(如 SIGINT、SIGTERM 等)
act: 指向新信号动作结构的指针,如果为 NULL 则不改变当前处理方式
oldact: 输出型参数,用于保存原信号动作结构的指针,如果为 NULL 则不保存
返回值
成功时返回 0,失败时返回 -1 并设置 errno。

struct sigaction {
    void     (*sa_handler)(int);         // 信号处理函数
    void     (*sa_sigaction)(int, siginfo_t *, void *); // 替代的信号处理函数
    sigset_t sa_mask;                    // 执行处理函数时要阻塞的信号
    int      sa_flags;                   // 修改行为的标志
    void     (*sa_restorer)(void);       // 已废弃
};

关于sa_mask变量

  1. 当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字(屏蔽该信号)
  2. 如果我们处理完对应的信号,该信号默认也会从信号屏蔽字中进行移除。(解除屏蔽该信号)
    为什么会这样?原因:不想让信号,嵌套式地对同一个信号进行捕捉处理。

用例子解释:

#include<iostream>
#include<signal.h>
void Print(sigset_t pending)
{
    std::cout<<" curr process pending: ";
    for(int sig = 31;sig > 0;sig--)
    {
        if(sigismember(&pending,sig)) std::cout << "1";
        else std::cout <<"0";
    }
    std::cout << std::endl;
}
void handler(int signo)
{
    std::cout << "signal: " << signo <<std::endl;
    //不断获取当前进程的pending信号集并打印
    sigset_t pending;
    sigemptyset(&pending);
    while(true)
    {
        sigpending(&pending);
        Print(pending);
        sleep(1);
    }
}

int main()
{
    struct sigaction act,oact;
    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);

    sigaction(2,&act,&oact);
    while(true)sleep;
}

在这里插入图片描述

在调用信号处理函数时,除了当前信号被自动屏蔽外,还希望自动屏蔽另外一些信号,则要用sa_mask字段说明。
例子:

int main()
{
    struct sigaction act,oact;
    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask,3);
    sigaddset(&act.sa_mask,4);
    sigaddset(&act.sa_mask,5);
    //除了屏蔽当前正在处理的函数,还屏蔽3,4,5号信号
    sigaction(2,&act,&oact);
    while(true)sleep;
}

相关文章:

  • 网站小编可以在家做吗运营推广渠道有哪些
  • 企业网站营销典型案例推广引流渠道
  • 汽车类网站搭建营销推广文案
  • 长沙专业的建站按效果付费seo公司重庆
  • 便宜网站制作行业关键词分类
  • 延安做网站的公司百度权重划分等级
  • Go 原理剖析:数据结构之字符串
  • 微服务组件——Eureka组件的安装与使用指南
  • 春秋云境(CVE-2023-23752)
  • Java高频面试之并发编程-02
  • MySQL 主从复制:数据库的克隆军团
  • ArcGIS/ArcGIS Pro地震分析:为什么缅甸地震,我国瑞丽震感最强烈?
  • 使用MetaGPT 创建智能体(1)入门
  • rbpf虚拟机-阶段整理
  • AVR128单片机密码锁
  • Flink在双流Join中,window如何选择
  • 【HCIA】静态综合实验练习笔记
  • JavaEE初阶复习(JVM篇)
  • 软考中级电子商务设计师分值分布解析!附最新备考资源!
  • Spark,上传文件
  • Spring | Spring、Spring MVC 和 Spring Boot 的区别
  • IntelliJ IDEA 2024.1.4 (Ultimate Edition)找不到Add Framework Support解决方法
  • 【diffusers 进阶(十五)】dataset 工具,Parquet和Arrow 数据文件格式,load dataset 方法
  • XT1870 同步升压 DC-DC 变换器
  • WebView加载URL时添加时间戳可以防止缓存问题方案
  • ceph数据迁移数据迁移与bacula配置调整优化实战