【Linux】详解用户态和内核态内核中信号被处理的时机sigaction信号自定义处理方法

本文主要是介绍【Linux】详解用户态和内核态内核中信号被处理的时机sigaction信号自定义处理方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、用户态和内核态的理解

        在操作系统中,用户态和内核态是两种主要的执行模式,它们代表了不同的访问级别和权限,用于确保系统的安全和稳定性。

1.1、用户态

        用户态是操作系统中用户进程的运行状态。在这种状态下,进程只能访问受限的系统资源,并且不能执行某些特权操作。用户态下的进程没有权限直接访问硬件或执行某些敏感的系统调用。它们必须通过系统调用接口来请求内核态的服务。

1.2、内核态

        内核态是操作系统的核心部分(即内核)的运行状态。在这种状态下,代码可以访问系统内的所有内存空间,并且可以执行特权指令。内核态下的代码具有最高级别的权限,可以访问硬件、执行敏感操作,并管理系统资源。

1.3、用户态和内核态的切换时机

        当用户态下的进程需要执行特权操作时,它会通过系统调用接口向内核发出请求。这时,操作系统会保存用户态的上下文,然后切换到内核态来执行相应的服务。除了系统调用外,如硬件中断、软件异常也会导致系统从用户态切换到内核态。在这三种情况下,操作系统都会保存用户态的上下文,并在内核态下处理这些事件。

二、信号被处理的时机

        如下图所示,进程从内核态切换回用户态的时候,信号会被检测并处理。如果该信号的处理方法为默认处理方法,就不需要从内核态切换回用户态来处理我们写的方法,但如果该信号的处理方法为我们自己的自定义处理方法,就要从内核态切换回用户态来执行,执行完毕程序再进入内核。下面是进程处理信号并执行我们写的自定义处理方法的过程:

        执行信号自定义的处理方法时,可以由操作系统直接帮我们做了,但是为了避免我们写的处理方法存在非法操作,就必须切换回用户态, 由用户态的权限来约束我们是否能执行这个处理方法

三、用户态和内核态切换的内核级理解

在我们的进程地址空间中存在1G的内核空间,这部分会用来映射加载到内存中的操作系统。

         在内核中,所有的系统调用函数其实是被用一个函数指针数组所管理起来的,该函数指针数组会通过页表的映射与1G的内核空间的某些虚拟地址建立起映射关系,这样当正文代码部分要调用某个系统调用函数时,只需要拿着虚拟地址在内核空间中寻找再通过页表的映射就可以在内存中找到该系统调用函数。

        在系统中会存在多个进程,每个进程的地址空间的[0,3G]的地址空间映射的内容都不相同,但是,每个进程都要进行系统调用 ,也就意味着地址空间中的1G内核级空间所映射的内容可以完全相同。进一步说,我们的进程无论如何总能找到操作系统,我们的进程访问操作系统,都是通过进程地址空间中[3GB,4GB]这一部分空间来访问的。

        既然操作系统已经被映射到我们进程的地址空间上,那是否意味着我们可以随便访问操作系统中的内容了呢?答案肯定不是的。在CPU中有寄存器可以标识当前进程的状态(比如说00就表示处于用户态,11就表示处于内核态),如果进程处于用户态就阻止进程访问操作系统

四、设置自定义信号处理的函数

 设置自定义信号处理的函数除了signal函数外,还有一个sigaction函数。

        第一个参数为几号信号,第二个参数为一个描述新方法的结构体, 第三个参数为一个描述旧方法的结构体。

        该结构体中第一个成员变量为新设置的信号处理方法,第二个参数为类似于sa_handler,但它提供了更强大的功能,因为该函数还可以接收有关信号发送者的信息,可以设置为nullptr,第三个参数为一个信号集,可以用来设置在处理signum信号的同时所屏蔽的信号,第四个参数用于修改信号处理的某些默认行为,第五个参数通常不用于现代操作系统,不设置。 下面是一个sigaction函数使用的例子。

自定义2号信号的处理方法,让进程不断打印pending位图:

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;void print(sigset_t& pending)
{for(int i = 31; i>= 1; i--){if(sigismember(&pending, i))cout << "1";elsecout << "0";}cout << endl;
}//自定义2号信号的处理方法,让进程不断打印pending位图
void handler(int sig)
{sigset_t pending;sigemptyset(&pending);while(true){sigpending(&pending);print(pending);sleep(1);}
}

再让进程收到2号信号的同时阻塞3,4,5号信号:

int main()
{struct sigaction act,oact;act.sa_handler = handler;act.sa_flags = 0;cout << getpid() << endl;//清空要添加的信号集sigemptyset(&act.sa_mask);//让进程收到2号信号的同时阻塞3,4,5号信号sigaddset(&act.sa_mask, 3);sigaddset(&act.sa_mask, 4);sigaddset(&act.sa_mask, 5);sigaction(2, &act, &oact);while(true){}return 0;
}

最终运行结果:

        第一次给进程发送2号信号,信号被执行了所以pending位图中没有2号信号,再次发送2号信号发现pending位图中有2号信号,证明2号信号被屏蔽了,因为进程在处理某个信号时如果再次给它发送同一个信号该信号会被自动屏蔽,依次再向进程发送3,4,5号信号,发现信号都被屏蔽了。

这篇关于【Linux】详解用户态和内核态内核中信号被处理的时机sigaction信号自定义处理方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965243

相关文章

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分