操作系统导论--受限制的直接执行

news2025/8/12 10:37:00

受限直接执行

为了使程序尽可能快地运行,操作系统开发人员想出了一种技术——我们称之为受限的直接执行。

这个概念的“直接执行”部分很简单:只需直接在CPU上运行程序即可。因此,当OS希望启动程序运行时,它会在进程列表中为其创建一个进程条目,为其分配一些内存,将程序代码(从磁盘)加载到内存中,找到入口点(main()函数或类似的),跳转到那里,并开始运行用户的代码。

在这里插入图片描述

听起来很简单,不是吗?但是,这种方法在我们虚拟化CPU时产生了一些问题。

  • 第一个问题:如果我们只运行一个程序,操作系统怎么能确保程序只做我们允许它做的事情,同时仍然高效地运行它?

  • 第二个问题:当我们运行一个进程时,操作系统如何让它停下来并切换到另一个进程,从而实现虚拟化CPU所需的时分共享?

第一个问题

直接执行的明显优势是快速,让程序直接在硬件CPU上运行,因此执行速度与预期的一样快, 但这样就相当于让所有进程做所有它想做的事情,导致无法用程序构建一些系统;

例如: 如果我们希望构建一个具有相关读写访问权限的文件系统,就不能简单地让任何用户进程向磁盘发出I/O(即直接让该程序在CPU上运行),如果这样做,一个进程就可以任意读取或写入整个磁盘,这样所有的保护(权限)都会失效。

因此,我们采用的方法是引入一种新的处理器模式,称为用户模式(user mode)。在用户模式下运行的代码会受到限制。例如,在用户模式下运行时,进程不能发出I/O请求。这样做会导致处理器引发异常,操作系统可能会终止进程。

与用户模式不同的内核模式(kernel mode),操作系统(或内核)就以这种模式运行。在此模式下,运行的代码可以做任何它喜欢的事,包括特权操作,如发出I/O请求和执行所有类型的受限指令。

但是,如果用户希望执行某种特权操作(如从磁盘读取),应该怎么做?为了实现这一点,几乎所有的现代硬件都提供了用户程序执行系统调用的能力。它允许内核小心地向用户程序暴露某些关键功能,例如访问文件系统、创建和销毁进程、与其他进程通信,以及分配更多内存。

要执行系统调用,程序必须执行特殊的陷阱(trap)指令,该指令同时跳入内核并将特权级别提升到内核模式。一旦进入内核,系统就可以执行任何需要的特权操作(如果允许),从而为调用进程执行所需的工作。完成后,操作系统调用一个特殊的从陷阱返回(return-from-trap)指令,如你期望的那样,该指令返回到发起调用的用户程序中,同时将特权级别降低,回到用户模式。

为什么系统调用看起来像过程调用?

​ 你可能想知道,为什么对系统调用的调用(如open()或read())看起来完全就像C中的典型过程调用。也就是说,如果它看起来像一个过程调用,系统如何知道这是一个系统调用,并做所有正确的事情?原因很简单:它的确是一个过程调用,但隐藏在过程调用内部的是著名的陷阱指令。更具体地说,当你调用open()(举个例子)时,你正在执行对C库的过程调用。其中,无论是对于open()还是提供的其他系统调用,库都使用与内核一致的调用约定来将参数放在众所周知的位置(例如,在栈中或特定的寄存器中),将系统调用号也放入一个众所周知的位置(同样,放在栈或寄存器中),然后执行上述的陷阱指令。库中陷阱之后的代码准备好返回值,并将控制权返回给发出系统调用的程序。因此,C库中进行系统调用的部分是用汇编手工编码的,因为它们需要仔细遵循约定,以便正确处理参数和返回值,以及执行硬件特定的陷阱指令。现在你知道为什么你自己不必写汇编代码来陷入操作系统了,因为有人已经为你写了这些汇编。

还有一个重要的细节没讨论:陷阱如何知道在OS内运行哪些代码?很显然用户程序是不知道的,如果其知道的话,狡猾的用户便可以肆无忌惮的操作系统,不受权限控制了;

内核通过在启动时(处于内核模式)设置陷阱表来实现。当机器启动时,操作系统做的第一件事,就是告诉硬件在发生某些异常事件(如程序进行系统调用)时要运行哪些代码,因此当发送系统调用时候,陷阱便知道在哪里执行了

第二个问题

在进程之间切换应该很简单,操作系统应该决定停止一个进程并开始另一个进程,但实际上这有点棘手,因为当一个进程在CPU上运行时,就意味着操作系统没有运行,如果操作系统没有运行,它怎么能做事情?

所以我们碰到了关键问题:操作系统如何重新获取CPU的控制权;

历史上处理有两种方式:

  • 通过进程自己调用yield系统调用进行协作,归还CPU控制的控制权,没错,此系统调用仅仅只是用来归还控制权; 但这种方式很被动,例如,如果某个进程(无论是恶意的还是充满缺陷的)进入无限循环,并且从不进行系统调用,那么操作系统将永远也无法获得CPU控制权;
  • 利用时钟中断重新获得控制权 时钟设备可以编程为每隔几毫秒产生一次中断。产生中断时,当前正在运行的进程停止,操作系统中预先配置的中断处理程序(interrupt handler)会运行。此时,操作系统重新获得CPU的控制权,因此可以做它想做的事:停止当前进程,并启动另一个进程。

保存和恢复上下文

既然操作系统已经重新获得了控制权,无论是通过系统调用协作,还是通过时钟中断更强制执行,都必须决定:是继续运行当前正在运行的进程,还是切换到另一个进程;

如果决定进行切换,OS就会执行一些底层代码,即所谓的上下文切换(context switch)。

上下文切换在概念上很简单:操作系统要做的就是为当前正在执行的进程保存一些寄存器的值(保存到它的内核栈),并为即将执行的进程恢复一些寄存器的值(从它的内核栈取出)。

这样一来,操作系统就可以确保最后执行从陷阱返回指令时,不是返回到之前运行的进程,而是继续执行另一个进程。

为了保存当前正在运行的进程的上下文,操作系统会执行一些底层汇编代码,来保存通用寄存器、程序计数器,以及当前正在运行的进程的内核栈指针,然后切换内核栈,并恢复寄存器、程序计数器,供即将运行的进程使用。当操作系统最终执行从陷阱返回指令时,即将执行的进程变成了当前运行的进程。至此上下文切换完成

例如上图:

进程A正在运行,然后被中断时钟中断。硬件把它的进程数据保存到A的内存栈中,然互进入内核(切换到内核模式)。

在时钟中断处理程序中,操作系统决定从正在运行的进程A切换到进程B。此时,它调用switch()例程,该例程仔细保存当前寄存器的值(保存到A的进程结构),恢复进程B的寄存器(从它的进程结构),然后切换上下文(switch context),具体来说是通过改变栈指针来使用B的内核栈(而不是A的)。最后,操作系统从陷阱返回,开始运行进程B。

请注意,在此协议中,有两种类型的寄存器保存/恢复。

  • 第一种是发生时钟中断的时候(进程和OS之间的切换)。在这种情况下,运行进程的用户寄存器由硬件隐式保存,使用该进程的内核栈。

  • 第二种是当操作系统决定从A切换到B。在这种情况下,内核寄存器被软件(即OS)明确地保存,但这次被存储在该进程的进程结构的内存中。后一个操作让系统从好像刚刚由A陷入内核,变成好像刚刚由B陷入内核

小结

为了实现CPU虚拟化,我们描述了一些关键的底层机制,并将其统称为受限直接执行(limited direct execution)。

基本思路很简单:就让你想运行的程序在CPU上运行,但首先确保设置好硬件,以便在没有操作系统帮助的情况下限制进程可以执行的某些操作.

白话就是:

用户代码是程序,操作系统也是程序,但是后者可以做的事情更多,因此像涉及和硬件打交道的都交给OS处理,这个就是系统调用;

两个程序都需要CPU的运行,因此不可能一起运行,这就涉及当OS没有在CPU上运行时候,怎么确保它在一定时间内能继续控制整个计算机.

因此提供了两个方案: 给任何运行的用户程序一个yield调用,以及增加一个时钟硬件,到了一定时间就切换回来执行操作系统;

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

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

相关文章

Packet Tracer - 排除单区域 OSPFv2 故障

地址分配表 设备 接口 IP 地址 子网掩码 默认网关 R1 G0/0 172.16.1.1 255.255.255.0 不适用 S0/0/0 172.16.3.1 255.255.255.252 不适用 S0/0/1 192.168.10.5 255.255.255.252 不适用 R2 G0/0 172.16.2.1 255.255.255.0 不适用 S0/0/0 172.16.3.2 25…

slam定位学习笔记(六)

学习内容来自这篇文章,主要是将模块进行划分以及根据划分的模块对前面的代码结构进行调整。 一、模块划分 之前的文章主要介绍了这几个功能的实现:传感器时间同步、点云去畸变、实时显示点云、精度评价和前端里程计。将它们区分成三个模块:…

基于JSP的私人牙科医院管理系统【数据库设计、源码、开题报告】

数据库脚本下载地址: https://download.csdn.net/download/itrjxxs_com/86466989 主要使用技术 ServletJSPJSCSSMysql 功能介绍 登录注册模块:填写基本信息注册(普通用户)登录; 公告管理:公告增删改查&…

预训练模型分词方式

BPE、WordPiece、SentencePiece tokenize的目标是将输入的文本流, 切分成一个个子串,使得每个子串具有相对完整的语义,便于学习embedding表达和后续模型的使用。 tokenize三种粒度:word、subword、char word/词:最自…

Flutter高仿微信-第35篇-单聊-视频通话

Flutter高仿微信系列共59篇,从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图: 目前市场上第三方视频接口的价格高的吓人 视频通话价格: 标清&…

代码随想录算法训练营day55 | 392.判断子序列,115.不同的子序列

392.判断子序列 参考代码随想录算法训练营第五十五天 |392. 判断子序列、115. 不同的子序列 - 掘金 暴力解法: Time Complexity: O(M*N) Space Complexity: O(N) class Solution:def isSubsequence(self, s: str, t: str) -> bool:start 0 #used to make sur…

[附源码]java毕业设计医院网上预约系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Docker(9)DockerFile

文章目录什么是DockerFile构建过程执行DockerFile大致流程常用保留字DockerFile小案例创建dockerfile文件dockerfile内部脚本执行命令虚悬镜像什么是DockerFile DockerFile 使用来构建Docker镜像的文本文件,是由一条条构建镜像所需要的指令和参数组成脚本 构建过程…

CSDN Markdown 编辑器的目录与页内跳转功能

CSDN Markdown 编辑器的目录与页内跳转功能 文章目录CSDN Markdown 编辑器的目录与页内跳转功能 目录 页内跳转 正文内容跳转到标题正文内容跳转到正文内容结语目录 CSDN Markdown 编辑器的目录功能使用[TOC](你想要显示的目录总标题)格式,其中默认可省略括号及括…

2022-11-06 网工进阶(三十五)---PIM-SM工作原理(组播分发树的形成、ASM、SSM)

PIM-DM的局限性 中大型组播网络中由于网络较大,如果依然使用PIM-DM会遇到诸多问题: 1 使用“扩散-剪枝”方式需要全网扩散组播报文,对于网络有一定冲击。 2 所有组播路由器均需要维护组播路由表,即使该组播路由器无需转发组播数…

ARM-A架构入门基础(一)预备知识

14天学习训练营导师课程:周贺贺《ARMv8/ARMv9架构-快速入门》 1. 背景 ARM全称: Advanced RISC Machines。 ARM处理器: 基于ARM公司设计的架构而研发的处理器,包含arm core和外设。ARM公司本身不生产处理器,只出售技…

RNA-seq 详细教程:分析流程介绍(1)

学习目标 了解从 RNA 提取到获取基因表达矩阵, 既RNA-seq 分析的整个流程。 1. workflow 进行差异表达基因分析的前提是,获取代表基因表达水平的矩阵。因此在进行分析前,必须知道基因表达矩阵是如何产生的。 在本教程中,将会简要的…

基于JAVA的鲜花店商城平台【数据库设计、源码、开题报告】

数据库脚本下载地址: https://download.csdn.net/download/itrjxxs_com/86427660 摘要 在互联网不断发展的时代之下,鲜花软件可以为鲜花企业带来更多的发展机会,让企业可以挖掘到更多的潜在用户,同时结合企业的优势就能够为用户…

【单目标优化求解】粒子群混沌混合蝴蝶优化算法求解最优目标问题(HPSOBOA)【含Matlab源码 1538期】

⛄一、遗传算法简介 1 算法的种群初始化 设D维搜索空间中,随机生成初始解的表达式为: 式中,Xi表示蝴蝶群体中第i只蝴蝶(i 1, 2, 3, …, N)空间位置,N表示初始解的个数;Lb, Ub分别表示搜索空间的上界和下界&#xff…

Linux vmware 编译模块失败。 Vmware player Unable to install all modules.

Vmware player Unable to install all modules. See log for details ubuntu下的vmware play经常会让更新模块。一起点击确认就可以正常编译更新。 而且一定要编译后才能打开虚拟机系统 但是奇怪的是,最近一次点击 更新,报错: 显示的英文…

STM32F103的FSMC模块驱动LCD屏幕

以下内容为对正点原子的STM32F103STM32F103STM32F103精英板的FSMCFSMCFSMC模块驱动LCDLCDLCD屏幕例程的学习。做一个记录来加强对模块的认知。 FSMCFSMCFSMC的全称是FlexiblestaticmemorycontrollerFlexible\quad static\quad memory\quad controllerFlexiblestaticmemory…

【Python+Appium】开展自动化测试(四)使用weditor进行元素定位

目录 前言 一,weditor的安装与使用 二,遇到的问题 结语 前言 上一篇我们讲到了如何通过编写一个简单的Python脚本完成了登录app的操作,如何断言,如何编写一条完整的用例。那么今天继续我们的自动化测试第四天,使用…

【Java进阶篇】第五章 集合(下)--Map集合

文章目录1、概述2、Map接口中的常用方法3、Map集合的遍历4、哈希表的数据结构5、Map集合的存取6、hashCode()和equals()的重写7、一些小零散的东西8、HashMap和Hashtable的区别9、Properties类10、TreeMap11、自定义类实现Comparable接口12、二叉树13、Comparator接…

Caffeine《一》

《Caffeine(Java顶级缓存组件)一》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Caffeine(Java顶级缓存组件)》《Caffeine(Java顶级缓存组件)一》1. Caffeine缓存概念1.1 缓存的分…

【MyBatis】一、概述

框架 框架就是对通用代码的封装,提前写好了一堆接口和类,我们可以在做项目的时候直接引入这些接口和类,基于这些现有的接口和类进行开发,提高开发效率。 框架一般以jar包形式存在 三层架构 表现层(UI)&am…