深入分析Linux上下文与上下文切换

news2024/10/6 18:25:43

Linux 进程运行空间与特权等级

在 Linux 操作系统中,进程的运行空间被划分为内核空间和用户空间,这种划分是为了保护系统的稳定性和安全性。这两个空间对应着 CPU 的特权等级,分别为:

  • Ring 0(内核态)
  • Ring 3(用户态)
  • 本文将深入介绍这两个空间的概念、特权等级的含义以及它们之间的切换机制。

内核空间与用户空间

内核空间

内核空间是操作系统内核运行的区域,拥有最高的特权等级。在内核空间中,操作系统可以执行任意指令,访问所有硬件和内存资源。这包括对系统硬件、设备驱动程序和核心数据结构的完全访问。内核空间通常包含了操作系统的内核代码和数据结构。

用户空间

用户空间是供用户程序执行的区域,拥有较低的特权等级。在用户空间中,程序只能执行受限的指令,且对硬件资源的直接访问受到限制。用户空间包含了用户应用程序的代码和数据,以及一些共享库和用户环境的运行时信息。

CPU 特权等级

CPU 特权等级用于区分不同程序对计算机系统资源的访问权限。在 x86 架构中,特权等级被分为四个环,分别是:

  • Ring 0
  • Ring 3

Ring 0 拥有最高特权,而 Ring 3 拥有最低特权。

1. Ring 0 - 内核态

    Ring 0 是最高特权等级,对应内核空间。在 Ring 0 中,操作系统内核运行,可以执行任意指令,访问系统的全部资源。内核态下运行的代码可以执行特权指令,例如修改全局描述符表(GDT)和局部描述符表(LDT),以及执行 I/O 操作。

2. Ring 3 - 用户态

    Ring 3 是最低特权等级,对应用户空间。在 Ring 3 中,运行用户应用程序,程序只能执行非特权指令,访问受限资源。用户态下运行的代码无法直接执行一些特权指令,例如修改 GDT 和 LDT。必须通过系统调用陷入到内核中,才能访问这些特权资源。

上下文

Linux 是一个多任务操作系统,支持远远大于cpu数量的任务并行运行,但是从底层上看其实这些任务也不是同时运行,而是操作系统在非常短的时间内把CPU轮流分配给这些任务,这样在表象看起来像是多任务同时运行一样。

因为这些任务实际上是轮流使用cpu,所以在任务运行之前就得有地方记录这些任务的运行信息(需要加载什么信息,在哪里开始运行等)--CPU 寄存器和程序计数器。

在 Linux 操作系统中,当操作系统进行进程上下文切换时,通常会保存和恢复CPU 寄存器的状态,以及程序计数器的值。这确保了在切换回进程时,它能够继续执行先前被中断的位置。这是操作系统实现多任务和多进程并发执行的基本机制之一。

CPU 寄存器

  • 含义: CPU 寄存器是一组用于暂时存储数据的小型存储区域,直接嵌入在 CPU 中。寄存器在计算机中起到非常关键的作用,用于存储临时数据、地址、状态等信息。

  • 关联进程资源: 寄存器包括通用寄存器、特殊用途寄存器等。在进程上下文切换时,通用寄存器的值通常会被保存到进程的上下文中,以便在切换回该进程时能够恢复到之前的状态。

程序计数器(Program Counter,PC)

  • 含义: 程序计数器是一种特殊的寄存器,用于存储当前正在执行的指令的地址,即程序的下一条指令的地址。

  • 关联进程位置: 程序计数器的值指示了进程在内存中的特定位置,表示即将执行的指令的地址。在进程执行期间,计算机会不断更新程序计数器的值,使其指向下一条要执行的指令的地址。

CPU 寄存器和程序计数器。都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。

一句话总结上下文:

    在每个任务运行前,cpu需要知道任务是从哪儿运行的,然后从哪儿开始的,也就是说,需要系统给它设置好 CPU寄存器和程序计数器, cpu的寄存器是,cpu内置的容量小,但是速度极快的内存,而程序计数器,则是用来存储正在执行的指令位置,或者即将执行的吓一跳指令位置。他们是cpu在运行任何任务前,都必须依赖的环境(包括寄存器状态、内存映射、打开的文件、进程优先级等),因此也被叫做CPU上下文。

一句话总结上下文切换:

    就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

上下文切换

上下文切换是指操作系统在多任务环境下,从一个任务切换到另一个任务时保存和恢复这些上下文信息的过程。在 Linux 系统中,上下文和上下文切换是操作系统中关键的概念,对于系统性能和多任务处理有着重要的影响。

在多任务操作系统中,CPU 上下文切换是实现并发执行的关键机制。根据任务的不同,可以把上下文切换可以分成三种不同的上下文切换场景:进程上下文切换、线程上下文切换以及中断上下文切换。我们将从底层原理出发,详细介绍每种场景的具体实现和影响因素。

进程上下文切换

进程的上下文切换

    进程上下文切换是指从一个进程切换到另一个进程。它发生在多任务系统中,由调度器负责决定哪个进程获得 CPU 时间。上下文切换的开销包括保存当前进程的上下文、加载新进程的上下文以及刷新内存映射等。

系统调用的上下文切换

    在一开始介绍进程的运行空间与系统等级的时候,进程在从用户态到内核态的转变涉及系统调用,这里的系统调用也涉及上下文切换。系统调用是用户程序请求内核执行特权操作的方式,例如打开、读取或关闭文件。当进行文件内容查看等操作时,需要多次系统调用完成。每次系统调用都引发了 CPU 上下文的切换。

具体过程如下:

  1. 保存用户态: 在系统调用开始时,CPU 寄存器里保存着用户态的指令位置,需要先保存这些信息以便后续恢复。

  2. 进入内核态: 为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。

  3. 执行内核任务: 此时,CPU 进入内核态并执行相应的内核任务,完成系统调用的操作。

  4. 恢复用户态: 系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后切换回用户空间,继续运行进程。

一次系统调用的过程实际上发生了两次 CPU 上下文切换。

虽然系统调用过程中不涉及虚拟内存等用户态资源的切换,也不会切换进程,但实际上,CPU 的上下文切换是无法避免的。因此,系统调用过程中的上下文切换通常被称为特权模式切换,而非上下文切换。

进程上下文切换与系统调用的区别

进程上下文切换与系统调用有明显区别:

  1. 上下文内容:

    进程上下文切换包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。

    系统调用时,只保存和恢复了 CPU 寄存器和用户态的状态。

  2. 切换对象:

    进程上下文切换是在不同进程之间进行的

    系统调用过程中一直是同一个进程在运行

  3. 过程复杂度:

    进程上下文切换相对于系统调用更为复杂。它需要保存当前进程的内核状态和 CPU 寄存器之前,还需要保存该进程的虚拟内存、栈等;加载下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。

进程上下文切换的开销

上下文切换的过程并非“免费”,它需要内核在 CPU 上运行来完成。根据Tsuna的实验数据,每次上下文切换都需要几十纳秒到数微秒的 CPU 时间。在进程上下文切换次数较多的情况下,容易导致 CPU 时间主要花费在资源的保存和恢复上,而非真正的进程执行。

进程调度与上下文切换的时机

在 Linux 系统中,进程的调度并不仅仅发生在进程执行完终止的时候。我们来逐一梳理几个触发进程调度的场景,以加深对进程调度机制的理解。

1. 时间片耗尽
时机:
  • 当前运行进程的时间片耗尽。

为了保证所有进程能够得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片轮流分配给各个进程。当某个进程的时间片耗尽时,系统会挂起该进程,并切换到等待 CPU 的其他进程运行。

2. 系统资源不足
时机:
  • 进程等待某些系统资源(如内存)。

在系统资源不足的情况下(例如内存不足),进程需要等待资源满足才能继续运行。此时,该进程会被挂起,并由系统调度其他等待 CPU 的进程运行。

3. 睡眠函数
时机:
  • 进程主动调用睡眠函数(如 sleep)。

通过睡眠函数(如 sleep)等方式,进程可以主动挂起自己,等待一定的时间后再次被调度运行。

  1. 进程进入睡眠状态,不再占用 CPU 资源。

  2. 睡眠时间结束或被唤醒后,进程重新被调度运行。

4. 优先级更高的进程
时机:
  • 高优先级进程就绪并准备运行。

当有优先级更高的进程就绪时,为了确保高优先级进程能够及时运行,当前进程会被挂起,系统调度高优先级进程运行。

  1. 低优先级进程被挂起。

  2. 高优先级进程获得 CPU 控制权,运行相应任务。

  3. 执行完任务后,系统可能重新调度低优先级进程。

5. 硬件中断
时机:
  • 硬件设备产生中断。

发生硬件中断时,CPU 上正在执行的进程会被中断挂起,转而执行内核中的中断服务程序。一旦中断处理完毕,原先的进程可能会被重新调度运行。

  1. 当前进程被中断挂起。

  2. 中断服务程序执行。

  3. 中断处理完成后,可能重新调度原先的进程继续执行。

线程上下文切换

    线程上下文切换与进程上下文切换类似,但开销更小。因为线程共享相同的地址空间,切换时无需刷新内存映射。线程上下文切换通常发生在同一进程内的不同线程之间。

    线程(Thread)和进程(Process)是操作系统中用于执行程序的两个基本概念,在开始分析之前,我们先了解下线程与进程:线程是调度的基本单位,而进程则是资源拥有的基本单位

  1. 任务调度:

    • 线程是操作系统进行任务调度的基本单位。内核可以调度多个线程在同一进程中并发执行,充分利用多核处理器的性能。

    • 进程是一个独立的执行环境,它包含至少一个线程。但在内核的任务调度中,调度的对象是线程,而非整个进程。

  2. 资源拥有:

    • 进程是独立的资源拥有者,拥有独立的地址空间、文件描述符等。不同进程之间的资源是相互独立的。

    • 线程共享相同进程的资源,包括虚拟内存、文件描述符等。线程间的通信相对简单,因为它们共享相同的地址空间。

    • 线程也有自己的私有数据,比如栈和寄存器等。

  3. 调度效率:

    • 由于线程共享相同的资源,线程的创建、销毁和切换开销相对较小,调度效率较高。

    • 进程的独立性导致了较大的创建、销毁和切换开销,因为这涉及到整个地址空间的切换。

  4. 错误影响范围:

    • 一个线程的错误可能影响整个进程,因为它们共享相同的资源。这需要更加谨慎的编程和调试。

    • 进程的独立性使得一个进程的错误不太可能直接影响其他进程,提高了系统的稳定性。

线程上下文切换 可以分为两种情况

  1. 前后线程属于不同的进程。因为资源不共享,所以上下文切换的过程与进程上下文切换时一样的。

  2. 如果前后两个线程属于一个进程。因为虚拟内存是共享的,所以切换的时候 虚拟内存等资源是不用动的,只需要切换不同线程自己拥有的私有数据,寄存器等不共享的数据。

中断上下文切换

中断上下文切换是由硬件中断或软件中断触发的。当中断发生时,操作系统会保存当前进程或线程的上下文,然后转入中断服务例程执行。执行完中断服务例程后,操作系统会恢复之前保存的上下文,继续执行被中断的进程或线程。

中断上下文切换与进程上下文切换有着明显的区别。中断上下文切换并不涉及到进程的用户态,因此在中断过程中打断了一个正处在用户态的进程时,不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。相比之下,中断上下文只包括内核态中断服务程序执行所必需的状态,主要包括 CPU 寄存器、内核堆栈、硬件中断参数等。

中断上下文切换的特点:

  1. 内核态执行:

    • 中断上下文切换是在内核态下执行的,与用户态进程无关。因此,不需要保存和恢复用户态的资源。

  2. 资源限定:

    • 中断上下文主要关注于提供中断服务所需的最少资源,包括 CPU 寄存器、内核堆栈、硬件中断参数等。

    • 与进程上下文切换相比,中断上下文切换的资源范围较为有限,着重于满足中断处理的基本需求。

  3. 无需虚拟内存切换:

    • 由于中断上下文不牵涉用户态,因此无需切换虚拟内存。不同进程的虚拟内存空间在中断上下文中并不影响。

  4. 快速执行:

    • 中断上下文切换的目标是尽快响应硬件中断,因此切换过程相对迅速。

    • 这与进程上下文切换不同,后者可能涉及到更多的资源保存和恢复,因而相对较慢。

中断上下文切换的设计目标是最小化对系统性能的影响,专注于提供必要的执行环境以迅速处理硬件中断。这种机制使得操作系统能够高效地响应外部事件,保证系统的可靠性和实时性。

总结

上下文和上下文切换是操作系统中的关键概念,直接影响系统的性能和响应能力。了解上下文的概念以及上下文切换的过程有助于理解操作系统的工作原理,并能够优化程序以提高系统的性能和效率。在设计和开发多任务应用程序时,合理处理上下文切换是至关重要的。

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

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

相关文章

全国青少年劳动技能与智能设计大赛安徽省赛区赛前培训在肥东六中顺利举办

为推进我省青少年劳动教育和素质教育高质量发展,提升青少年家国情怀、多元思维、劳动技能、创新能力和综合素质,发现和培养创新后备人才。4月10日,肥东县教体局联合安徽省青少年劳动技能与智能设计大赛组委会在肥东六中创新科教基地成功举行全…

人工智能分类算法概述

文章目录 人工智能主要分类算法决策树随机森林逻辑回归K-均值 总结 人工智能主要分类算法 人工智能分类算法是用于将数据划分为不同类别的算法。这些算法通过学习数据的特征和模式,将输入数据映射到相应的类别。分类算法在人工智能中具有广泛的应用,如图…

目标检测——车牌图像数据集

一、重要性及意义 车牌图像识别的重要性及意义主要体现在以下几个方面: 智能交通管理:车牌图像识别技术是智能交通系统(ITS)的核心组成部分。通过自动识别车辆车牌,可以实现对交通违章行为的自动记录和处理&#xff…

SSD涨价停不下来!

随着HBM内存产能短缺问题的出现,存储市场正遭遇另一波供应短缺。在2021年存储市场陷入低迷后,SSD价格已连续下滑约两年。面对市场变化,存储厂商减少了NAND闪存的生产。随着减产策略的有效执行,需求部分回升,导致SSD供应…

jni 开发 调用dll 函数的流程

jni 调用dll方法以及dll内调用java方法的流程 编写java类 public class abc{static{System.loadLibrary("abc.dll");}public String getResponse(String ReqStr) {return "ok";}public native void InitDiagObj();public native void CarryabcEntry(Stri…

C++的并发世界(十一)——线程池

0.线程池的概念 1.线程池使用步骤 ①初始化线程池:确定线程数量,并做好互斥访问; ②启动所有线程 ③准备好任务处理基类; ④获取任务接口:通过条件变量阻塞等待任务 2.atomic原子操作 std:atomic是C11标准库中的一个…

双碳目标下太阳辐射预报模式【WRF-SOLAR】及改进技术在气象、农林、电力等相关领域中的应用

太阳能是一种清洁能源,合理有效开发太阳能资源对减少污染、保护环境以及应对气候变化和能源安全具有非常重要的实际意义,为了实现能源和环境的可持续发展,近年来世界各国都高度重视太阳能资源的开发利用;另外太阳辐射的光谱成分、…

A Note on LoRA

A Note on LoRA 摘要Additional InsightsPractical ImprovementsLooking Ahead 摘要 LoRA已成为一种首选的方法,用以高效地适应大型语言模型(LLM),其简便性和有效性令人瞩目。本文档扩展了原始LoRA论文,提供了最初未讨…

Spring中的适配器模式

在Spring MVC框架中,适配器模式主要体现在对不同类型的处理器(即Controller)的统一处理上。Spring MVC通过适配器模式来保证无论Controller的实现方式如何多样化,都能够被DispatcherServlet统一调用和管理。具体使用方式如下&…

李廉洋:4.10黄金原油晚间走势最新分析及策略。

鉴于美联储官员对1月和2月通胀数据反应不足,3月通胀数据过热可能导致其反应过度的风险更大。美联储试图避免根据一两个数据点来制定政策,但今年迄今为止经济活动的韧性意味着,在年中降息的理由取决于通胀是否恢复自去年下半年以来的稳步下降趋…

uniapp小程序编译报错

说明 微信小程序编译每次都出现[ project.config.json 文件内容错误] project.config.json: libVersion 字段需为 string, 解决 找到manifest.json文件 添加:"libVersion": "latest",重新编译即可。

Redis常见数据类型(2)

目录 String字符串 常见命令 SET GET MGET MSET SETNX 计数命令 INCR INCRBY DECR DECRBY INCRFLOAT 其它命令 APPEND GETRANGE SETRANGE STRLEN String字符串 字符串是Redis最基础的数据类型, 关于字符串需要特别注意: (1)首先Redis中所有的键的类型都是字符…

[leetcode]remove-duplicates-from-sorted-list-ii

. - 力扣(LeetCode) 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 示例 1: 输入:head [1,2,3,3,4,4,5] 输出:[1,2,5]示例 2&…

jvm中jdk常用的几个命令总结

1.jmap 此命令可以用来查询内存信息&#xff0c;实例个数及占用内存大小 1.1 查看堆内存概要信息&#xff08;内存分配统计&#xff09; jmap -histo[:live] <pid> .-histo&#xff1a;显示堆中对象的统计信息&#xff0c;包括每个类的实例数量、占用内存大小等 :live…

互联网产品经理必备知识详解

1. 前言 本文档全面探讨了产品经理在产品管理过程中的关键环节,包括市场调研、产品定义及设计、项目管理、产品宣介、产品市场以及产品生命周期。通过深入剖析这些方面,本文旨在帮助产品经理系统地理解和掌握产品管理的核心要素,从而提升产品开发的效率和成功率。在市场调研…

HarmonyOS 开发-二级联动

介绍 本示例主要介绍了List组件实现二级联动&#xff08;Cascading List&#xff09;的场景。 该场景多用于短视频中拍摄风格的选择、照片编辑时的场景的选择。 效果图预览 使用说明&#xff1a; 滑动二级列表侧控件&#xff0c;一级列表随之滚动。点击一级列表&#xff0c;…

运行vue项目

将命令改为&#xff1a; 1 npm run dev vite 不是内部分外部命令 报错信息&#xff1a;"vite 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件" 通常意味着 Vite 没有被安装或者没有正确地添加到系统的环境变量中。 解决方法&#xff1a; 确认 V…

HAL ST32F4 定时器2触发ADC转换

HAL ST32F4 定时器2触发ADC转换 &#x1f4cd;相关篇《STM32 F401/411外设内部互联矩阵摘要》《STM32G070RBT6基于STM32CubeMX创建ADC DMA多通道采样工程》 &#x1f4dd;利用定时器2的更新中断触发ADC转换。与定时器中断中调用ADC转换不同。前者是内部更新事件触发ADC转换&…

美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了

写在开头 今天在牛客上看到了一个帖子&#xff0c;一个网友吐槽美团一面上来就让手撕同步器&#xff0c;没整出来&#xff0c;结果面试直接凉凉。 就此联想到一周前写的一篇关于AQS知识点解析的博文&#xff0c;当时也曾埋下伏笔说后面会根据AQS的原理实现一个自定义的同步器…

05 Php学习:类型比较、常量

PHP 类型比较 虽然 PHP 是弱类型语言&#xff0c;但也需要明白变量类型及它们的意义&#xff0c;因为我们经常需要对 PHP 变量进行比较&#xff0c;包含松散和严格比较。 松散比较&#xff1a;使用两个等号 比较&#xff0c;只比较值&#xff0c;不比较类型。严格比较&#x…