进程信号以及用户态和内核态的理解

news2024/11/24 16:04:53

文章目录

    • 什么是进程信号?
    • 用户层产生信号的方式有哪些?
    • 信号在内核的存在形式
    • 认识信号的一些接口
    • 信号处理的执行流程
      • 理解用户态和内核态
      • 信号处理流程

什么是进程信号?

进程信号是一种事件异步通知机制,属于软件中断(因为信号产生时是异步的,当信号产生时,对应的进程可能正在做更重要的事情,我们的进程可以暂时不处理这个信号)

在linux中使用kill -l可以查看所有信号,如下(共有62种):
在这里插入图片描述
inux 内核支持 62 种不同的信号,这些信号都有一个名字,这些名字都以三个字符 SIG 开头。在头文件siganl.h中你能够,这些信号都被定义为正整数,称为信息编号。其中,编号 1 到 31 的信号称为普通信号,编号 34 到 64 的信号称为实时信号,实时信号对处理的要求比较高。

普通信号和实时信号的关系就像分时操作系统和实时操作系统的关系类似,分时操作系统是基于时间片轮转调度的,而实时操作系统要求要有严格的时序,可以认为是一个队列。将一个任务放入该队列中,那么操作系统就尽量快地将该任务处理完。日常生活中使用最多的就是分时操作系统,而实时操作系统常见于特殊的行业,如军工领域和自动驾驶领域等等。
分时系统

所谓分时系统,即一台计算机与多个终端设备连接,每个用户通过终端向系统发出命令,请求系统为其完成某项工作。系统根据用户的请求完成指定的任务,并把执行结果返回。
分时系统思想

  1. 采用时间片轮转的方法,同时为多终端用户服务,对每个用户能保证足够快的响应时间,并提供交互会话的功能
  2. 时间片:将CPU的时间划分成若干个片段,称为时间片,操作系统以时间片为单位,轮流为每个终端用户服务
  3. 设计目标:对用户的请求及时响应,并在可能条件下尽量提高系统资源的利用率

实时系统

所谓“实时”,是指能够及时响应随机发生的外部事件并对事件做出快速处理的一种能力。
“外部事件”,是指与计算机相连接的设备向计算机发出的各种服务请求
实时操作系统是能对来自外部的请求和信号在限定的时间范围内做出及时响应的操作系统

信号的内核数据结构(Linux2.6环境下)
前面说当信号产生时,对应的进程可能正在做更重要的事情,我们的进程可以暂时不处理这个信号。
但是我们的进程必须记住这个信号,那么这个信号保存在哪里呢?
保存在我们进程的PCB里,也就是task_struct里
在Linux中,task_struct结构体中表示信号的字段是signal。该字段是一个指向signal_struct结构体的指针,它包含了当前进程所设置的所有信号的信息,包括信号的处理方式、挂起的信号等。这些信息被用来决定何时向进程发送信号以及如何处理这些信号。signal_struct结构体中还有其他的字段,例如sigaction、sigmask等,它们用于存储信号的处理方式和信号掩码等信息。

用户层产生信号的方式有哪些?

  1. 用户可以通过键盘输入kill命令对指定的进程进行发送信号(但是键盘只是产生信号,OS才是写入(发送信号)
  2. 可以通过系统接口完成对进程发送信号的(比如signal,kill等等,后面对这些接口再详细说明)
  3. 可以通过软件条件发送信号(alarm函数, 调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程)
  4. 通过硬件异常产生信号(比如除0错误)(硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除 以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。)

信号在内核的存在形式

信号的一些概念

  • 实际执行信号的处理动作称为信号递达(Delivery)
  • 信号从产生到递达之间的状态,称为信号未决(Pending)。
  • 进程可以选择阻塞 (Block )某个信号。
  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
  • 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作
    在这里插入图片描述

这里解释一下上面的示意图,每个进程PCB也就是task_struct,会记录该进程的信号情况,类似上图;我们知道信号有62种,在图中可以看出每个信号都有两个标志位分别表示阻塞(block)和未决(pending)还有一个函数指针表示当该信号发送后,就会执行这个指向的函数。
block和pending都是一个位图,在上图中SIGINT信号产生过,但是正在被阻塞,所以暂时不能递达,所以pending是1。

如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?
Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可 以依次放在一个队列里。当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来 的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。

认识信号的一些接口

signal函数

sighandler_t signal(int signum, sighandler_t handler);
功能:为signum信号,注册一个回调方法,如果有信号发送给当前进程,就会执行handler方法

什么是sigset_t

sigset_t我们称为信号集,其实就是一个位图,这个类型可以表示每个信号 的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有 效”和“无效”的含义是该信号是否处于未决状态。
信号集操作接口

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
  • 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号。
  • 函数sigfillset初始化set所指向的信号集,然后把所有的信号加入到此信号集里。
  • 注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的 状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号

sigprocmask

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 

返回值:若成功则为0,若出错则为-1 
  • 如果oset是非空指针,set是空指针,则读取进程的当前信号屏蔽字通过oset参数传出
  • 如果set是非空指针,oset是空指针,则更改进程的信号屏蔽字。
  • 如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽。
  • how参数有几个取值

SIG_BLOCK :参数set包含了我们希望添加到当前信号的屏蔽字的信号
SIG_UNBLOCK:参数set包含了我们希望从当前信号屏蔽字中解除阻塞的信号。
SIG_SETMASK:设置当前信号屏蔽字为set所指向的值
sigpending

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 

返回值:若成功则为0,若出错则为-1 
#include <signal.h>
sigpending

读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。 下面用刚学的几个函数做个实验。程
序如下:

代码:

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "我是一个进程,获取到一个信号:" << signo << endl;
    exit(0);
}

static void showPending(sigset_t *pendings)
{
    for(int sig = 1; sig <= 31;sig++)
    {
        if(sigismember(pendings,sig))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}


int main()
{
    //给2号信号注册一个方法
    signal(2,handler);
    //添加2号信号到信号屏蔽字中
    sigset_t bsig,obsig;
    sigemptyset(&bsig);
    sigemptyset(&obsig);
    sigaddset(&bsig,2);
    sigprocmask(SIG_SETMASK,&bsig,&obsig);
    //获取当前进程pending信号集
    sigset_t pendings;
    int cnt = 0;
    while(true)
    {
        sigemptyset(&pendings);
        if(sigpending(&pendings) == 0)
        {
            //打印当前信号集
            showPending(&pendings);
        }
        sleep(1);
        cnt++;
        if(cnt == 10)
        {
            cout << "解除对所有信号的block" << endl;
            sigprocmask(SIG_SETMASK,&obsig,nullptr);
        }
    }
    return 0;
}

信号处理的执行流程

理解用户态和内核态

在介绍信号处理的执行流程之前,我们先来了解什么是用户态和内核态
在这里插入图片描述
在图中我们可以看出,进程地址空间分为两部分,一部分是用户空间,一部分是内核空间;页表也分为两种一种是用户级页表,一种是内核级页表。
用户级页表:每一个进程,都有一份,而且大家的用户级页表都是不一样的!

内核级页表:所有进程共享的只有一份,前提是你有权利访问

那到底什么是内核态,什么是用户态呢?
用户态是指应用程序运行时所处的状态,而内核态是指操作系统内核运行时所处的状态。

当应用程序需要访问操作系统提供的资源或执行一些特权操作时,需要切换到内核态,由操作系统内核来完成相应的操作。在内核态下,应用程序无法直接访问系统资源和硬件设备,需要通过操作系统提供的接口来进行操作。

相比之下,用户态下的应用程序只能访问自己的内存空间和一些受限的资源,不能直接访问操作系统的资源和硬件设备,也不能执行特权操作。用户态和内核态之间的切换需要一定的时间和资源,因此应该尽量减少切换的次数,以提高系统的性能和稳定性。

简单来说,内核态可以访问所有的代码和数据,具有更高的权限;而用户态只能访问自己的

进程如果是用户态——只能访问用户级页表(只能访问用户的代码和数据)
进程如果是内核态——访问内核级和用户级页表(可以访问所有代码和数据)
那我们的进程什么时候会进入内核态呢?

  1. 调用系统接口的时候(此时就会切换内核级页表,通过页表映射到物理内存存放内核代码和数据的地方,执行系统接口的代码)
  2. 时间片到了,进程间的切换(要执行调度代码等等)

怎么知道当前进程是用户态的还是内核态的呢?

CPU内部有对应的状态寄存器CR3,有比特位标识当前进程的状态;0表示内核态,3表示用户态

信号处理流程

理解了什么是内核态,什么是用户态,我们就可以来理解信号的执行流程了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/627775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手机充电流程

手机的整个充电过程由充电管理IC 控制的&#xff0c;完整的充电过程可以分为6个阶段&#xff1a;涓流充电模式、预充电模式、恒流充电模式、恒压充电模式、充电完成模式、二次充电模式。 完整的充电过程 1. 涓流充电模式 涓流充电一般以很小的电流&#xff08;几十到一百毫安…

LeetCode - 15 三数之和

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满…

【Android】WMS(四)WMS职责

WMS职责 WMS&#xff08;Window Manager Service&#xff09;是 Android 系统中的一个系统服务&#xff0c;它是WindowManager的管理者&#xff0c;负责对窗口进行管理、分配资源&#xff0c;以及处理用户的输入事件等问题。WMS是整个系统中非常重要的一个组成部分&#xff0c;…

昨晚技术交流群“炸了”,论搞技术的网络工程师究竟能有多严谨?

昨日在IELAB网络实验室学习交流群中发生了一场“激烈”的争论&#xff0c;原本是同往常一样的答题领红包活动&#xff0c;同学对答案产生了异议&#xff0c;从而和Summer赵老师在群里进行了沟通交流&#xff0c;具体是什么情况呢&#xff1f; IELAB每日答题活动 于是乎&#xf…

JMeter 测试笔记(一):认识JMeter

引言&#xff1a; 在现代互联网时代&#xff0c;应用程序的性能已经成为了一个非常重要的问题&#xff0c;并且对于许多公司的生存和发展都起着至关重要的作用。 而JMeter作为一个免费且开源的性能测试工具&#xff0c;可以帮助我们进行各种类型的性能测试&#xff0c;如接口…

阿里巴巴最新开源:Java工程师面试笔记(30万字精华总结 + 面试1300问)吊打面试官绰绰有余

前言 作为一个 Java 程序员&#xff0c;你平时总是陷在业务开发里&#xff0c;每天噼里啪啦忙敲着代码&#xff0c;上到系统开发&#xff0c;下到 Bug 修改&#xff0c;你感觉自己无所不能。然而偶尔的一次聚会&#xff0c;你听说和自己一起出道的同学早已经年薪 50 万&#x…

网卡中的Ring buffer -- 解决 rx_resource_errors 丢包

1、软硬件环境 硬件&#xff1a; 飞腾E2000Q 平台 软件&#xff1a; linux 4.19.246 2、问题现象 网卡在高速收包的过程中&#xff0c;出现 rx error , 细查是 rx_resource_errors 如下&#xff1a; rootE2000-Ubuntu:~# ifconfig eth1 eth1: flags4163<UP,BROADCAST,RU…

Amazon SageMaker:探索AI绘画云端部署新方案

目录 1 从艺术实验到AI绘画2 什么是Amazon SageMaker&#xff1f;3 云端部署AI绘画应用3.1 模型构建与部署3.2 AI绘画测试(文生图) 4 亚马逊云科技中国峰会 1 从艺术实验到AI绘画 在过去&#xff0c;人们只希望基于已有的给定数据做一些预测和拟合&#xff0c;因此判别式模型得…

RFID资产盘点在企业的应用

随着新技术的发展&#xff0c;企业在不断地进行转型&#xff0c;企业为了更好地发展&#xff0c;对企业内部的管理工作越来越重视。在管理中&#xff0c;如何利用先进的科学技术来提高管理效率&#xff0c;成为了企业发展的关键。在资产管理上&#xff0c; RFID技术在资产盘点和…

TCP三次握手建立连接和四次挥手断开连接

TCP的连接与断开 TCP 通过三次握手建立连接&#xff0c;以建立确保数据传输的参数&#xff0c;连接的双方都将初始化与 TCP 连接相关的许多 TCP 状态变量。该连接是一条逻辑连接&#xff0c;其共同状态仅保留在二个通信端系统的TCP程序中。 TCP连接的组成包括&#xff1a;一台…

上门服务app开发|上门服务系统定制打开家政服务的大门

上门服务app可以为用户带来更加便捷的服务体验&#xff0c;不需要用户出门寻找服务商&#xff0c;只需要通过小程序下单即可享受到上门服务&#xff0c;省去了用户的时间和精力。同时上门服务app也为服务商提供了一个更广阔的市场&#xff0c;他们可以通过上门服务系统向更多的…

走进科学之sudo rm -rf,为什么如此危险

关注微信公众号“网络安全学习圈”&#xff0c;回复暗号【网络安全】&#xff0c;立即领取最新网安教程全家桶。 什么是 sudo rm -rf&#xff1f; sudo rm -rf 是一个linux的命令行命令&#xff0c;用于在系统中删除文件和目录。sudo表示以管理员权限运行该命令。rm是remove…

OPEN AI 全新版本来了2.0.0永久免费在线体验构建AI开放生态

V2.0.0 更新内容 后台整体功能重构完善后台增加订阅接口服务后台会陆续扩展订阅更多AI接口服务后台增加分销推广功能OPEN AI注册增加邮箱验证绑定OPEN AI开发者插件生态构建后台分销推广额度累计支持提现现金后台支持查询官方账号key使用量和余量开放接口提供账号绑定和订阅接…

【ChatGLM】记录一次Windows部署ChatGLM-6B流程及遇到的问题

文章目录 部署环境文件下载项目文件模型配置文件模型文件 运行demo遇到的问题 部署环境 系统版本&#xff1a;Windows 10 企业版 版本号&#xff1a;20H2 系统类型&#xff1a;64 位操作系统, 基于 x64 的处理器 处理器&#xff1a;Intel Core™ i7-8700 CPU 3.20GHz 3.19 GH…

软考A计划-电子商务设计师-模拟试题卷四

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

NX/UG二次开发—Parasolid—PK_EDGE_ask_convexity

判断实体边的凸凹性 Convexity Value Example convex PK_EDGE_convexity_convex_c concave PK_EDGE_convexity_concave_c variable the convexity varies along the edge PK_EDGE_convexity_variable_c smooth flat parallel surface normals, both faces have zero f…

cli3 非父子组件传值

这里&#xff0c;App.vue中&#xff0c;引入了parent组件&#xff1b;parent组件中引入了child组件。现在要从app.vue&#xff0c;向child组件传值。 主要文件&#xff1a; 1. 通过事件总线传值 1. src ->util->bus.js // 通过util中的bus&#xff0c;完成两个组件之间…

你的Postman为什么连不了数据库?

postman本身没有数据库连接功能&#xff0c;所以用到了node.js中的xmysql实现Rest API的生成&#xff0c;利用postman进行请求&#xff0c;获取需要的数据&#xff0c;来做数据准备或断言 1.安装 安装node.js&#xff1a;要求版本大于等于7.6 首先保证你的环境上有node.js&a…

打工人,别着急摆烂,看看你到底值多少钱?

2023求职现状&#xff1a; HR&#xff1a;看简历&#xff0c;以为能造飞机&#xff0c;招进来以后发现螺丝都不会拧。 普通求职者&#xff1a;看公司招聘要求&#xff0c;以为这个岗位是造飞机的&#xff0c;没想到进去以后是拧螺丝的。 大龄求职者&#xff1a;以前我都是造飞…

1.平台介绍:FISCO-BCOS 区块链

&#xff08;1&#xff09;概念: FISCO BCOS是由国内企业主导研发、对外开源、安全可控的企业级金融联盟链底层平台。它以联盟链的实际需求为出发点&#xff0c;兼顾性能、安全、可运维性、易用性、可扩展性&#xff0c;支持多种SDK&#xff0c;并提供了可视化的中间件工具&am…