我是靠谱客的博主 高挑大树,最近开发中收集的这篇文章主要介绍【操作系统】Operation System-第2章-启动 & 中断、异常 和 系统调用操作系统—启动 & 中断、异常 和 系统调用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

操作系统—启动 & 中断、异常 和 系统调用

启动

image-20220518193347866

  • DISK:存放OS

    ➢ 在DISK上,还存在Bootloader,用于加载OS,将OS从硬盘加载到内存中

  • BIOS:基于I/O处理系统

计算机启动流程

image-20220518201624647

启动时计算机内存和磁盘布局

image-20220518194236903

从一个特定地址开始执行:CS:IP = 0xf000:fff0 分别代表这两个寄存器的值(CS:段寄存器;IP:指令寄存器) ,这两个寄存器合在一起可以形成一个具体的内存地址。

一开始加电,BIOS就从这个内存地址开始执行,POST(加电自检),寻找显卡和执行BIOS。

一些基本的操作都要由BIOS来进行初始化的检查。

检查完发现这些显卡以及外设都是可以正常工作的,接下来就需要把bootloader从硬盘放到内存中。

加载程序(bootloader)

image-20220518201735716

加载程序的内存地址空间

image-20220518200155639

Bootloader放在硬盘的第一个主引导扇区(512字节)。BIOS从硬盘的第一个扇区寻找,一下便找到Bootloader,Bootloader再负责加载OS。

之后,由Bootloader将操作系统的代码和数据从硬盘加载到内存中。之后,控制权交给到OS(跳转到OS的起始地址)。

操作系统与设备和程序交互

定义

  • 中断(hardware interrupt) 来源于外设

    ➢ 来自不同的硬件设备的计时器和网络的中断

  • 异常(exception) 来源于不良的应用程序

    ➢ 非法指令或者其他坏的处理状态(如:内存出错)

  • 系统调用(system call) 来源于应用程序

    ➢ 应用程序主动向操作系统发出服务请求

为什么应用程序不能直接访问我们的外设,而要通过操作系统呢?

  • 在计算机运行中,内核是被信任的第三方
  • 只有内核可以执行特权指令
  • 为了方便应用程序

中断、异常和系统调用比较

image-20220518220212858

异步:应用程序不知道什么时候会发生

同步:执行到某一条指令一定会发生

中断和异常处理机制

  • 中断是外设的事件
  • 异常是内部CPU的事件
  • 中断和异常迫使CPU访问一些被中断和异常服务访问的功能。

中断流程

硬件

设置中断标记(CPU初始化)

  • 将内部、外部事件设置中断标记
  • 中断事件的ID(指程序访问的中断向量地址 => 找到对应的处理历程)

软件

  • 保存当前处理状态(寄存器的内容等),便于后续恢复时 能正常使程序从被中断的点继续往下执行
  • 中断服务程序处理
  • 清楚中断标记
  • 恢复之前保存的处理状态

因此,应用程序完全不用感知到中断的产生。

异常处理流程

得到异常编号

  • 保存现场

  • 异常处理

    ➢ 杀死了产生异常的程序

    ➢ 重新执行异常指令

  • 恢复现场

系统调用

操作系统服务的编程接口

系统调用来源于应用程序 需要操作系统提供服务,这些服务需要操作系统来执行,这个过程就需要一个接口:系统调用接口

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

标准C库的例子

image-20220518224134349

三种最常用的应用程序编程接口(API):

  • Win32 API 用于Windows
  • POSIX API 用于 POSIX-based systems(包括UNIX,LINUX,Mac OS X)
  • Java API 用于JAVA虚拟机(JVM 跨平台)

实现

  • 通常情况下,每个系统调用对应一个系统调用号

    • 系统调用接口根据这些序号来维护表的索引
  • 系统调用接口调用内核态中预期的系统调用

    • 并返回系统调用的状态和其他任何返回值
  • 用户不需要知道系统调用是如何实现的

    ➢ 只需要获取API和了解操作系统将什么作为返回结果

    ➢ 操作系统接口的细节大部分都隐藏在API中

    ​ √ 通过运行程序支持的库来管理(用包含编译器的库来创建函数集)

函数调用和系统调用的不同处

image-20220518230006581

用户态:操作系统运行中,级别特别低,不能访问特权指令

内核态:操作系统运行中,级别很高,可以执行任何一条指令,包括特权指令

用户态和内核态的区别

系统调用:触发CPU从用户态到内核态的特权级转换,切换程序和内核的堆栈,需要一定的开销

函数调用只是在一个栈空间完成参数的传递以及返回。

当执行系统调用时,它带来的开销会比函数调用要大很多,当然这个开销是有回报的(安全、可靠,且是必须要付出的代价)。

跨越操作系统边界的开销

这些代价 确保整个系统 安全、可靠,正常运行

  • 在执行时间上的开销超过程序调用

  • 开销:

    ➢ 建立中断/异常/系统调用号与对应服务例程映射关系的初始化开销(建表)

    ➢ 建立内核堆栈

    ➢ 验证参数

    ➢ 内核态映射到用户态的地址空间(更新页面映射权限)

    ➢ 内核态独立地址空间(TLB)

系统调用示例

image-20220523161647695

image-20220523162652178

系统调用库接口示例

image-20220523162707059

image-20220523162810459

整理自 【清华大学】 操作系统

最后

以上就是高挑大树为你收集整理的【操作系统】Operation System-第2章-启动 & 中断、异常 和 系统调用操作系统—启动 & 中断、异常 和 系统调用的全部内容,希望文章能够帮你解决【操作系统】Operation System-第2章-启动 & 中断、异常 和 系统调用操作系统—启动 & 中断、异常 和 系统调用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部