【操作系统笔记八】任务调度信号处理CPU上下文

news2024/11/26 10:22:06

任务调度

何时需要调度执行一个任务?

  • 第一:当任务创建的时候,需要决定是继续执行父进程,还是调度执行子进程

  • 第二:在一个任务退出时,需要做出调度决策,需要从 TASK_RUNNING 状态的所有任务中选择一个任务来执行

  • 第三:当一个任务阻塞在 I/O 上,或者因为其他原因阻塞,必须调度另一个任务执行

  • 第四:在一个 I/O 中断发生时,必须做出调度决策。

    I/O 中断来源于 I/O 设备,说明 I/O 的工作结束了,需要唤醒正在阻塞在这个 I/O 上的进程,这个时候,调度程序要决定是否调度这个被唤醒的任务。

  • 第五:时钟中断发生的时候

在这里插入图片描述

问题:如何实现对响应时间敏感的调度程序?

  • 轮转调度(Round-Robin, RR)

  • 基本思想:在一个时间片内运行一个任务,时间片结束,然后切换到下一个任务,而不是运行一个任务直到结束。这样反复执行,直到所有任务完成。

  • RR 有时被称为时间切片,时间片长度必须是时钟中断周期的倍数。如果时钟中断是每 10ms 中断一次,则时间片可以是 10ms20ms10ms 的任何倍数。

信号处理

什么是信号?

例如 kill -9 2334,内核先找到pid = 2334的进程,并杀掉这个进程以及 tgid = 2334 的线程。

  • 给进程2334发送9号信号:SIGKILL

  • 一共有 64 个信号:kill -l

  • 信号是很短的消息,可以被发送到一个进程或一组进程

  • 每个信号,本质上就是一个数字而已

在这里插入图片描述

信号处理大体流程:

在这里插入图片描述

信号发送:

  • kill(pid, sig):向 pid 所在的线程组发送一个sig号信号

  • tkill(pid, sig):向 pid 进程(或线程)发送一个sig号信号

  • tgkill(pid, sig, tgid):向 pid 进程(或线程)发送一个sig号信号(检查下这个进程的tgid是否等于参数中的 tgid

给一个线程组发送的信号,称为共享信号,给一个进程/线程发送的信号,称为私有信号。

信号已发送,但未处理的信号称为挂起信号,存储在 task_struct

在这里插入图片描述
在这里插入图片描述

信号处理:

每个信号都有默认的处理方式:

  • Terminate:终止进程(杀死)

  • Dump:终止进程(杀死),将进程运行的上下文信息保存到文件中,方便查询进程相关信息

  • Ignore:信号被忽略

  • Stop:停止进程,将进程的状态设置为TASK_STOPPED

  • Continue:如果进程的状态是TASK_STOPPED,那么把它 设置为 TASK_RUNNIND

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

CPU 上下文、进程上下文以及中断上下文

CPU 上下文

在 CPU 执行程序指令的时候,需要一系列的 CPU 寄存器来存储 CPU 计算时要用到的指令、临时数据等。

第一个是指令指针寄存器 (eip 或者 rip),这个其实就是我们平时说的 程序计数器 (PC),它是 CPU 中最重要的寄存器了

  • 32 位系统的话,寄存器的名字以 e 开头
  • 64 位系统的话,寄存器的名字以 r 开头

它里面存储的是:下一条需要执行的指令在内存中的虚拟地址。CPU 的工作就是不断从内存中取出它指向指令,然后执行这一条指令,同时将下一条指令在内存的地址存放到指令寄存器中。如此不断重复,这就是 CPU 的工作了。

第二个是通用寄存器,一般用于存储 CPU 执行指令过程中产生的中间数据,一般有下面的寄存器:

  1. eax / rax:通常用于执行加法,函数调用的返回值一般也放在这里
  2. ebx / rbx:存放中间临时数据
  3. ecx / rcx:通常用于计数器
  4. edx / rdx:用于存放整数除法产生的余数
  5. esp / rsp:函数调用栈的栈顶指针,指向栈的顶部
  6. ebp / rbp:函数调用栈的栈底指针,指向栈的底部
  7. esi / rsi:存放中间临时数据
  8. edi / rdi:存放中间临时数据

这些通用寄存器是程序执行时最常用的,也是最基础的寄存器,程序执行过程中,绝大部分时间都是在操作这些寄存器来实现指令的功能。

第三个是标志寄存器 (flags),里面有众多标记位,记录了 CPU 执行指令过程中的一系列状态,这些状态大都由 CPU 自动设置。

我们在【操作系统一:程序是如何运行的?】中的第 11 小节 中,讲的 if 语句的汇编指令中,就使用了标记寄存器中的零标志条件码 (Zero Flag) 这一位标志码,来实现程序指令的跳转功能。

在这里插入图片描述

第四个是段寄存器,段寄存器用于分段寻址,虽然 Linux 内核采用分页寻址,但是为了保持兼容,段寄存器有些地方仍然在使用,所以,我们还需要关心,段寄存器有 6 个:

  1. CS:代码段
  2. DS:数据段
  3. SS:栈段
  4. ES:扩展段
  5. FS
  6. GS

总结:

  • 指令指针寄存器、通用寄存器、标志位寄存器以及段寄存器,这四组寄存器共同构成了一个基本的指令执行环境,也可以称为 CPU 上下文

  • 每个寄存器,CPU 中只有一个,比如指令指针寄存器,在 CPU 中只有一个

  • 每个进程在执行的时候,都会有各自的 CPU 上下文信息,也就是说每个进程执行的时候,CPU 中的寄存器的值都有可能不同的

系统调用引起的 CPU 上下文切换

知道了什么是 CPU 上下文,就很容易理解 CPU 上下文切换,CPU 上下文切换就是 CPU 把前一个进程的 CPU 上下文保存起来,然后再加载新的进程的 CPU 上下文,这样,CPU 就可以根据指令指针中存放的新的指令内存地址,执行新的进程了。

其实,CPU 上下文切换就是修改 CPU 中的寄存器的值而已

保存下来的 CPU 上下文,会存储在系统内核中,但是具体被保存在哪里呢?这个需要看具体的场景,我们先来看看系统调用

操作系统将进程的运行空间分为内核空间和用户空间:

  • 内核空间具有最高的权限,可以直接访问所有的资源

  • 用户空间只能访问受限资源,不能直接访问磁盘等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。

进程在用户空间运行时,也就是 CPU 执行用户程序代码,被称为进程的用户态。

而陷入内核空间的时候,那么 CPU 将执行内核程序代码,被称为进程的内核态。

从用户态陷入内核态,需要通过系统调用来完成。在系统调用的过程中会发生 两次 CPU 上下文切换

  1. 首先将进程的用户态的 CPU 上下文保存到内核栈的 pt_regs 中,然后,为了执行内核的代码指令,操作系统需要将 CPU 寄存器的值更新为内核态相关的值,然后开始执行内核态程序
  2. 当系统调用结束后,将内核栈中的 pt_regs 中的用户态的 CPU 上下文,恢复到 CPU 寄存器中,然后切换用户空间,继续运行进程

注意:系统调用过程中一直是在同一个进程中进行的。

进程 / 线程上下文切换

一个进程的上下文信息包含:

  1. CPU 上下文
  2. 用户态虚拟内存,即 mm_struct,这个里面包含了进程页表
  3. TLB 页表项缓存数据
  4. 磁盘文件信息
  5. 信号处理信息
  6. 内核栈

在一个进程里,所有的线程共享进程的资源,比如虚拟内存、磁盘文件、信号处理等,不过线程也有自己的数据,一个线程的上下文包含:

  1. CPU 上下文
  2. 线程用户栈
  3. 线程内核栈

在 Linux 中线程是 CPU 任务调度的最小单位。

一个 CPU 同一时刻只能调度执行一个线程,所以,多线程运行的时候,肯定会出现线程切换。

线程切换又分为三种情况:

  1. 切换的两个线程是在同一个进程内
  2. 切换的两个线程不在同一个进程内
  3. 切换的两个线程有一个是内核线程

接下来我们分别来看下以上三种情况。

第一种情况:切换的两个线程在同一个进程内。 这种情况下需要做下面的几件事:

  1. 切换 CPU 上下文
  2. 切换用户栈
  3. 切换内核栈

第二种情况:切换的两个线程不在同一个进程内。 这种情况下需要做下面的几件事:

  1. 切换 CPU 上下文
  2. 切换用户态虚拟内存 (这里会切换用户栈)
  3. 切换页表
  4. 刷新 TLB 页表项缓存
  5. 切换内核栈

可以看出切换两个不在同一个进程的线程,其实就是切换进程上下文了,比切换在同一个进程中的两个线程开销要大。

第三种情况:切换的两个线程中有一个是内核线程。 这种情况下需要做下面的几件事:

  1. 切换 CPU 上下文
  2. 切换内核栈

因为内核线程只运行在内核,没有用户空间的虚拟内存,所以不需要切换用户态虚拟内存、不需要切换页表,也就不需要刷新 TLB。这样的话,内核线程切换的开销也不大。

中断上下文切换

为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。

而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行。

跟进程上下文不同,中断上下文切换并不涉及到进程的用户态。

所以,即便中断过程打断了一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、磁盘文件、信号处理等用户态资源。

中断上下文,其实只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存器、内核堆栈、硬件中断参数等。

对同一个 CPU 来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生。

同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。

另外,跟进程上下文切换一样,中断上下文切换也需要消耗 CPU,切换次数过多也会耗费大量的 CPU,甚至严重降低系统的整体性能。

所以,当你发现中断次数过多时,就需要注意去排查它是否会给你的系统带来严重的性能问题。

总结

  • CPU 上下文一组 CPU 寄存器,包括:指令指针寄存器、通用寄存器、标志位寄存器以及段寄存器,不同进程切换时切换 CPU 上下文就是指切换 CPU 寄存器中的值

  • 系统调用会发生 2 次 CPU 上下文切换,从用户态陷入内核态, 首先将进程的用户态的 CPU 上下文保存到内核栈中,然后操作系统需要将 CPU 寄存器的值更新为内核态相关的值,开始执行内核态程序代码指令,当系统调用结束后,将内核栈中的用户态的 CPU 上下文,恢复到 CPU 寄存器中,然后切换用户空间,继续运行进程

  • 进程 / 线程上下文切换时,也会发生 CPU 上下文切换

    1)如果是在同一个进程内的两个线程切换,则需要切换CPU上下文、用户栈内核栈

    2)如果是在不同进程的两个线程切换,则需要切换CPU上下文、用户栈内核栈,还需切换页表,刷新TLB页表项缓存,此时就是切换两个进程

    3)如果切换的两个线程中有一个是内核线程,则只需要切换CPU上下文内核栈,因为内核线程只运行在内核,没有用户空间的虚拟内存,所以不需要切换用户态虚拟内存、不需要切换页表

  • 中断上下文切换不会涉及进程的用户态,只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存器、内核堆栈、硬件中断参数等

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

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

相关文章

IDEA 2019 Springboot 3.1.3 运行异常

项目场景&#xff1a; 在IDEA 2019 中集成Springboot 3.1.3 框架&#xff0c;运行异常。 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…

Linux ❀ 进程出现process information unavailable时的消除方法

[rootmaster ~]# jps 74963 -- process information unavailable 78678 Jps [rootmaster ~]# cd /tmp/hsperfdata_redhat/ # redhat为启动该java进程的用户ps -ef | grep $pid查找 [rootmaster hsperfdata_redhat]# ll total 32 -rw------- 1 redhat redhat 32768 Sep 27 15:…

GaussDB数据库SQL系列-游标管理

目录 一、前言 二、概述&#xff08;GaussDB&#xff09; 1、游标概述 2、游标的使用分类 三、GaussDB中的显式游标&#xff08;示例&#xff09; 1、显式游标的使用与操作步骤 2、显式游标示例 四、GaussDB中的隐式游标&#xff08;示例&#xff09; 1、隐式游标简介…

python+requests接口自动化测试框架实例详解

前段时间由于公司测试方向的转型&#xff0c;由原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行的接口测试&#xff0c;后来&#xff0c;组内有人讲原先web自动化的测试框架移驾成接口的自动化框架&#xff0c;使用的…

通讯网关软件015——利用CommGate X2MQTT实现MQTT访问Modbus RTU

本文介绍利用CommGate X2MQTT实现MQTT访问Modbus RTU。CommGate X2MQTT是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;SCADA系统上位机、PLC、设备具备Modbus RTU通讯接口&#xff0c;现在…

缓存雪崩、缓存击穿、缓存穿透

缓存雪崩 当缓存中大量的键值对同时过期或者Redis宕机了&#xff0c;大量的请求就会直接打到数据库&#xff0c;这种现象就是缓存雪崩 应对策略 有四种&#xff0c;分别是“均匀设置过期时间”、“互斥锁”、“双key策略”、“设置逻辑过期时间&#xff0c;异步更新缓存” …

WiFi产品认证通常需要准备哪些材料

我们做WiFi产品&#xff0c;都需要做一些认证。比方说FCC、CE、SRRC等认证。 认证需要准备很多材料。通常WiFi产品的认证需要准备的材料如下&#xff1a; 认证需要准备材料

解决使用flex布局引起的变形问题

只需在变形的样式中加以下代码&#xff0c;禁止拉伸就ok了 flex-shrink: 0;

【技巧】Ubuntu临时授予用户sudo权限,并在一定时间后自动撤销

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 目录 背景说明 开始操作 at指令 背景说明 有时候普通用户需要使用sudo来执行一些操作&#xff0c;作为服务器管理员&#xff0c;需要盯着该用户使用完后再给他撤销sudo权限。当用户多起来的时候&#xff0c;这…

游戏设计模式专栏(一):工厂方法模式

引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 在游戏开发中&#xff0c;代码的组织和结构对于项目的可…

Centos 7 部署SVN服务器

一、安装SVN 1、安装Subversion sudo yum -y install subversion2、验证是否安装成功&#xff08;查看svn版本号&#xff09; svnserve --version二、创建版本库 1、先建立目录&#xff0c;目录位置可修改 mkdir -p /var/svn cd /var/svn2、创建版本库&#xff0c;添加权限…

web前端tips:js继承——寄生式继承

上篇文章给大家分享了 js继承中的 原型式继承 web前端tips&#xff1a;js继承——原型式继承 今天给大家分享一下 js 继承中的 寄生式继承 寄生式继承 寄生式继承&#xff08;Parasitic Inheritance&#xff09;是一种基于原型式的继承方式&#xff0c;它通过创建一个仅用于…

电气专业发展到头了?

今日话题 电气专业发展到头了&#xff1f; 电气绝对不是末路专业。但是有个前提&#xff0c;不要选错行业。大土木类的&#xff0c;不管是设计还是施工&#xff0c;都不要选择。 二、电网公司。电网是绕不开的话题&#xff0c;早些年电网待遇太好&#xff0c;搞得大家都理所…

最优化问题简介

最优化问题&#xff08;也称优化问题&#xff09;泛指定量决策问题&#xff0c;主要关心如何对有限 资源进行有效分配和控制&#xff0c;并达到某种意义上的最优&#xff0e;它通常需要对需求进 行定性和定量分析&#xff0c;建立恰当的数学模型来描述该问题&#xff0c;设计合…

SI3262:国产NFC+MCU+防水触摸按键三合一SoC芯片

目录 SI3262简介特点结构框图芯片特性 SI3262简介 Si3262是高度集成ACD低功耗MCUNFC15通道防水触摸按键的SoC芯片。 其MCU模块具有低功耗、Low Pin Count、宽电压工作范围&#xff0c;集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、TSC等丰富的…

WebGL雾化

目录 前言 如何实现雾化 线性雾化公式 雾化因子关系图 根据雾化因子计算片元颜色公式 示例程序&#xff08;Fog.js&#xff09; 代码详解​编辑 详解如何计算雾化因子&#xff08;clamp()&#xff09; 详解如何计算最终片元颜色&#xff08;根据雾化因子计算片元颜色…

KongA 任意用户登录漏洞分析

KongA 简介 KongA 介绍 KongA 是 Kong 的一个 GUI 工具。GitHub 地址是 https://github.com/pantsel/konga 。 KongA 概述 KongA 带来的一个最大的便利就是可以很好地通过UI观察到现在 Kong 的所有的配置&#xff0c;并且可以对于管理 Kong 节点 漏洞成因 未设置TOKEN_SECRE…

智能报修系统哪家好?有什么扫码一键报修的软件?

这是一套to b系统&#xff0c;专门为企事业单位提供日常的故障报修服务&#xff0c;单位员工遇到任何故障可扫码提交到平台上&#xff0c;再由平台根据技术维修员的擅长方向派单至技术维修员手中&#xff0c;全程可以跟踪报修的进度&#xff0c;每月可以导出维修记录&#xff0…

QT编译报错stdlib.h:No such file or directory

如图&#xff0c;需要将第19行&#xff0c;INCLUDEPATH /usr/include 注释掉 原因分析&#xff1a; 在Ubuntu的CSTDLIB中&#xff0c;使用的是#include_next下“stdlib.h” &#xff0c;自行增加/usr/include 把include_next的顺序打乱&#xff0c;造成编译错误。但是在cento…

Qt 画自定义饼图统计的例子

先给出结果图&#xff0c;这个例子是将各种事件分类然后统计的其比例&#xff0c;然后画饼图显示出来 这个是我仿照官方给的例子&#xff0c;让后自己理解后&#xff0c;修改的&#xff0c;要生成饼图&#xff0c;需要QT的 charts 支持&#xff0c;安装QT 没有选择这个的&#…