01 地址空间与物理空间、操作系统的调用、异常和中断

地址空间

  • 物理地址空间:硬件支持的地址空间
  • 逻辑地址空间:一个运行的程序所拥有的内存范围

逻辑地址的生成:在C语言中函数、变量的名称就是一种逻辑地址,(一个c语言程序,经过编译之后,变成一个汇编程序.s,汇编程序经过汇编器转换成机器语言程序.o .c地址是一个从0开始的连续的地址空间(逻辑地址),通过linker链接应用程序将多个.o程序变成一个单一执行程序.exe,可由内存执行,目前存放在硬盘中的一个程序,通过载入loader这种应用程序把放在硬盘中的可执行程序放置到内存中去执行,此时逻辑地址映射到内存中的具体地址(仍然是一个逻辑地址,只不过此时的逻辑地址不是用具体的符号表示,而是用二进制数表示),存在一定的偏移量)。

  • CPU中存在一个内存管理单元MMU,用于存放逻辑地址和物理地址的映射关系。
  • 执行一条指令的过程,首先CPU中的计算逻辑单元ALU读取指令的内容,CPU通过指令的逻辑地址LA查找指令的物理地址PA,通过查CPU中MMU中的映射关系(查存放在内存中的一个映射表)完成这项操作,知道物理地址后,CPU就可以把指令从内存中相应的位置取过来,然后执行指令。

物理地址的生成过程:

  • CPU方面:
    • 运算器ALU需要知道指令的内容,发出请求读取指令的逻辑地址
    • 内存管理单元MMU寻找逻辑地址和物理地址之间的映射关系
    • CPU中的控制器从总线发送在物理地址的内存的内容的请求。
  • 内存方面:
    • 内存发送物理地址内存的内容给CPU
  • 操作系统方面
    • 建立逻辑地址和物理地址之间的映射

1.7 操作系统结构
  • 简单的操作系统(微软):MS-DOS(1981~1994),不分模块的单体内核
  • Unix操作系统是1972由(Knneth Thompson和Dennis Ritchie在贝尔实验室设计,由C语言设计完成(汇编语言的特点,与具体的机器绑定,不具有可移植性)
  • 微内核设计,尽可能把内核功能移到用户空间(内核里面只放置最基本的功能,例如中断服务等),
  • 学术界存在另一种更加极端的架构,“外核”,
  • VMM(虚拟机监视器):将单独的机器接口转换成很多的幻想,每个这些接口(虚拟机)是一个原始计算机系统的有效副本,并完成所有的处理器命令。(充分利用计算机的硬件资源)

2.1 操作系统的启动

DISK:存放OS

BIOS:基本I/O处理系统(计算机上电开机之后,计算机系统能够检测各种各样的外设,之后加载相应的软件进行执行)。包括包BootLoader加载到内存当中去。

  • 将BootLoader从磁盘的引导扇区(512K)加载到0x7c00.

Bootloader:一个小程序,用于加载OS,让OS从硬盘放入到内存当中去,让CPU可以执行操作系统,操作系统加载到内存中的地址是固定的。(放在硬盘的第一个主引导扇区,512个字节大小),此时CPU的控制权由BootLoader掌控。

  • 将操作系统的代码和数据从硬盘加载到内存中,此时CPU的控制权有BootLoader转交到OS,计算机所有的硬件处在OS的管理之下。

POST(加电自检):检查自身的各种各样的设备是否能够正常的工作(显卡、键盘、鼠标等)


系统调用接口(System Call Interface)之系统调用、异常、中断

系统调用(来源于应用程序):应用程序主动向操作系统发出服务请求,需要操作系统提供相应的支持,可以理解为应用程序向操作系统发出的特殊指令,让操作系统去完成相应的功能。

异常:(来源于不良的应用程序):非法指令或其他坏的处理状态(如:内存出错),应用程序在执行过程中出现的一些意想不到的事情,使得不得不由操作系统来完成相应的功能。

中断(来源于外设):来自不同的硬件设备的计时器和网络中断。通过中断可以让操作系统知道有外设发出了请求,需要处理了。

问题:为什么应用程序不能够直接去访问外设呢,为什么需要通过操作系统(对整个计算机具有控制权,是一个可以信任的软件)?

  • 在计算机运行中,内核是被信任的第三方,如果让应用程序直接去调用外设,很容易导致计算机的崩溃
  • 只有内核可以执行特权指令
  • 为了方便应用程序,对于应用程序而言,操作系统向下屏蔽了复杂了的硬件设备,向上提供了简单的接口。

它们三者之间有什么样子的不同?

  • 产生的源头不同
    • 中断产生于外设
    • 异常是应用程序意想不到的行为
    • 系统调用是应用程序请求操作系统提供服务
  • 处理的时间不同
    • 中断:异步,即当某个事件产生之后我们的应用程序并不知道什么时候回产生
    • 异常:同步,执行某条指令之后一定会产生,比如除零操作等
    • 系统调用:异步或同步,发出系统调用请求是同步的,应用程序发出执行某条指令之后立即发出系统调用,但是操作系统的系统调用的返回可能是同步的也有可能是异步的。
  • 处理响应的状态是不同的
    • 中断:持续,对用户应用程序是透明的。它打断了当前应用程序的正常执行,但是应用程序并没有感知到有中断的产生。
    • 异常:杀死或者重新执行意想不到的应用程序指令
    • 系统调用:等待和持续,应用程序等待服务完成之后就继续执行

2.2 中断和异常的处理机制(处理过程)

中断处理分为硬件和软件两部分去完成

硬件:当外设需要操作系统提供相应的服务支持,会产生一个标记,让CPU知道中断产生了,CPU看到这个标记之后CPU可以知道到底产生的什么中断,从而产生 一个 具体的中断号,之后把中断号发送给操作系统,操作系统可以根据这个中断号找到对应的处理历程。

  • 设置中断标记【CPU的初始化】
    • 将内部、外部时间设置中断标记
    • 中断事件的ID
  • 软件(操作系统)
    • 保存当前的处理状态即被打断的执行现场,便于后续从被打断的点继续执行
    • 根据CPU产生的的中断号,找到对应中断处理历程的地址,跳到对应位置执行即中断服务程序的处理
    • 清除中断标记
    • 恢复之前保存的处理状态(这个过程对应用程序是透明的,应用程序完全感知不到中断的产生)

异常的处理过程:

  • 异常:异常编号
    • 保存现场
    • 异常处理
      • 杀死产生了异常的程序
      • 重新执行异常指令
    • 恢复现场

系统调用的详细分析

系统调用是来源于应用程序,需要操作系统提供服务,而这些服务不能由应用程序直接来执行,必须要由操作系统来执行。这个过程就需要有一个接口,这个接口称之为系统调用接口,有了这些接口之后,就可以让操作系统为应用程序提供各种各样的服务。

例如应用程序调用printf()时,会触发系统调用write(),需要包含参数,像要用哪一个设备显示这个字符串,以及字符串的内容。

知识点补充:

操作系统是用户与计算机硬件系统之间的接口,用户通过操作系统的帮助,可以快速、有效和安全、可靠地操纵计算机系统中的各类资源,以处理自己的程序。为使用户能方便地使用操作系统,OS 又向用户提供了如下两类接口:

(1) 用户接口:操作系统专门为用户提供了“用户与操作系统的接口” ,通常称为用户接口。该接口支持用户与 OS 之间进行交互,即由用户向 OS 请求提供特定的服务,而系统则把服务的结果返回给用户。

(2) 程序接口:操作系统向编程人员提供了“程序与操作系统的接口” ,简称程序接口,又称应用程序接口 API(Application Programming Interface)。 该接口是为程序员在编程时使用的,系统和应用程序通过这个接口,可在执行中访问系统中的资源和取得 OS 的服务,它也是程序能取得操作系统服务的唯一途径。大多数操作系统的程序接口是由一组系统调用(system call)组成,每一个系统调用都是一个能完成特定功能的子程序 [2] 。

应用程序接口又称为应用编程接口,是一组定义、程序及协议的集合,通过 API接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集。API同时也是一种中间件,为各种不同平台提供数据共享。程序设计的实践中,编程接口的设计首先要使软件系统的职责得到合理划分。良好的接口设计可以降低系统各部分的相互依赖,提高组成单元的内聚性,降低组成单元间的耦合程度,从而提高系统的可维护性和可扩展性。

程序的访问主要是通过高层次的API接口而不是直接进行系统调用

  • ​ Win32 API 用于Windows
  • POSIX (一个通用可移植的标准)API 用于POSIX-based Systems(包括UNIX、LINUX、Max OS X的所有版本)
  • Java API 用于 JAVA虚拟机(JVM)

用户态:指的是应用程序执行的过程中CPU所处于的一个特权级的状态,此特权级非常的低,不能够直接的访问某些特殊的机器指令和直接访问I/O

内核态:操作系统运行过程中CPU所处于的一种状态,在这种状态下,操作系统可以执行任何的指令。

用户态转变到内核态可以使得计算机的安全性得到保障

  • 应用程序通过系统调用接口(system call interface)完成从用户态到内核态的转换

系统调用与传统的函数调用的区别

  • 当应用程序发出函数调用的时候是在一个栈空间完成函数之间参数的传递和参数的返回
  • 当应用程序执行系统调用的过程中:应用程序和操作系统拥有各自的堆栈,意味着当应用程序发出系统调用之后,切换到内核中去执行的时候,需要切换堆栈,还需要完成特权级的转换,从用户态转换到内核态。这两种转化都需要一定的系统的开销,这就意味着执行系统调用的时候所需要的系统开销会比执行函数调用的开销大很多。大的开销的回报就是安全、可靠。

跨越操作系统边界的具体开销:(这些开销是值得的,它能够保证操作计算机在一个安全可靠的环境下执行)
  • 建立中断、异常、系统调用号与对应服务例程映射关系的初始化开销

  • 建立内核堆栈

  • 验证参数

  • 内核态映射到用户态的地址空间

  • 更新页面映射权限

  • 内核态独立地址空间


提示:为了更好的理解知识点,博主在微信公众号中将操作系统知识进行了重新排版和插入图片。感兴趣的朋友可以扫码进行关注。

在这里插入图片描述

发布了19 篇原创文章 · 获赞 1 · 访问量 716

猜你喜欢

转载自blog.csdn.net/weixin_45615071/article/details/105505021