首页 > 其他分享 >MIT6.S081 - Lecture3: OS Organization and System Calls

MIT6.S081 - Lecture3: OS Organization and System Calls

时间:2024-04-20 11:12:00浏览次数:28  
标签:Lecture3 操作系统 Calls MIT6 应用程序 mode 内核 CPU 内存

为什么要使用操作系统

  1. 使用操作系统的主要原因是为了实现 CPU 多进程分时复用以及内存隔离
  2. 如果没有操作系统,应用程序会直接与硬件进行交互,这时应用程序会直接使用 CPU,比如假设只有一个 CPU 核,一个应用程序在这个 CPU 核上运行,但是同时其他程序也需要运行,因为没有操作系统来帮助切换,就需要应用程序时不时释放 CPU 资源,但是如果这个程序的某个函数有一个死循环,那它就永远也不会释放 CPU,甚至没办法做到运行第三方程序来停止或者杀死这个死循环程序,这种情况下就没办法实现 CPU 多进程的分时复用
  3. 还有从内存的角度来看,如果应用程序直接运行在硬件上,则程序的数据代码都直接保存到物理内存中,这样不同程序的内存之间没有明确边界,就可能会造成一个程序存储在本来属于另外一个程序的内存空间,覆盖另外一个程序中的内容

操作系统的隔离性需要隔离用户程序和操作系统,也需要隔离不同的进程

系统调用与隔离性

  • 可以认为 exec 抽象了内存。当我们在执行 exec 系统调用的时候,我们会传入一个文件名,而这个文件名对应了一个应用程序的内存镜像。内存镜像里面包括了程序对应的指令,全局的数据。应用程序可以逐渐扩展自己的内存,但是应用程序并没有直接访问物理内存的权限,例如应用程序不能直接访问物理内存的 1000-2000 这段地址。不能直接访问的原因是,操作系统会提供内存隔离并控制内存,操作系统会在应用程序和硬件资源之间提供一个中间层。exec 是这样一种系统调用,它表明了应用程序不能直接访问物理内存。
  • files 基本上是抽象了磁盘。应用程序不会直接读取磁盘,在 Unix 中它与存储系统交互的唯一方式就是通过 files。操作系统会决定如何将文件与磁盘中的块对应,确保一个磁盘块只出现在一个文件中,并保证用户 A 不能操作用户 B 的文件。files 实现了不同用户之间以及同一用户不同进程之间的文件隔离

硬件实现强隔离性

实现强隔离性的硬件支持包括了两部分:

  1. user/kernel mode:处理器有两种操作模式:user mode 和 kernel mode:

    • 当运行在 kernel model 时,CPU 能运行特定权限的指令(直接操作硬件的指令和设置保护的指令,如设置 page table 寄存器、关闭时钟中断)
    • 当运行在 user mode 时,CPU 只能运行普通权限的指令

    RISC-V 实际上有三种权限:user/kernel/machine mode

  2. 在 RISC-V 中,如果你在用户空间(user space)尝试执行一条特殊权限指令,用户程序会通过系统调用来切换到 kernel mode。当用户程序执行系统调用,会通过 ECALL 触发一个软中断(software interrupt),软中断会查询操作系统预先设定的中断向量表,并执行中断向量表中包含的中断处理程序。中断处理程序在内核中,这样就完成了 user mode 到 kernel mode 的切换,并执行用户程序想要执行的特殊权限指令

  3. 虚拟内存:每个进程都有自己独立的 page table,page table 将虚拟内存地址和物理内存地址做了对应

ECALL 指令

  • 在 RISC-V 中,ECALL 指令可以让用户程序将控制权转移给内核,并传入一个数字,这个数字表示了应用程序想要调用的 System Call
  • ECALL 会跳转到内核中一个特定的位置,在内核侧,有一个位于 syscall.c 的函数 syscall,每一个从应用程序发起的系统调用都会调用到这个 syscall 函数,syscall 函数会检查 ECALL 的参数

内核是如何夺回控制权

  • 内核会通过硬件设置一个定时器,定时器到期之后会将控制权限从用户空间转移到内核空间,之后内核就有了控制能力并可以重新调度 CPU 到另一个进程中

宏内核 vs 微内核

宏内核

XV6 中,所有的操作系统服务都在 kernel mode 中,这种形式被称为宏内核

  • 从安全的角度来说,这种方式不太好,在一个宏内核中,任何一个操作系统的 Bug 都有可能成为漏洞,如果有许多行代码运行在内核中,那么出现严重 Bug 的可能性也变得更大
  • 宏内核的优势在于可以将文件系统、虚拟内存、进程管理这些实现特定功能的子模块紧密地集成在一起,这样可以提供很好的性能

微内核

微内核模式下,在内核中只有非常少的模块,将内核中的其他部分作为普通的用户程序来运行

  • 这样做的好处是内核中的代码数量较小,降低了 bug 出现的可能
  • 如果用户程序想要使用内核的功能,但由于内核的程序作为普通的用户程序,比如说某个系统想要使用文件系统,需要完成从用户空间到内核空间,再从内核到用户空间来访问文件系统,文件系统也需要经过同样的路径将消息返回给用户系统,使得在微内核从用户到内核的跳转是宏内核的两倍,而反复跳转带来了性能的损耗,且微内核的内核程序被隔离开,难以实现共享,降低了系统的性能。

XV6 代码结构

代码主要由三部分组成:

  1. kernel:包含了基本上所有的内核文件
  2. user:这基本上是运行在 user mode 的程序
  3. mkfs:会创建一个空的文件镜像,将这个镜像存在磁盘上,就可以直接使用一个空的文件系统

kernel 编译过程

  1. Makefile 读取一个 C 文件,比如 proc.c,然后调用 gcc 编译器,生成一个叫 proc.s 的文件,这是 RISC-V 汇编语言文件,然后再走到汇编解释器,生成 proc.o,这是汇编语言的二进制格式,Makefile 会为所有内核文件做相同的操作
  2. 系统加载器收集所有的.o 文件,将它们链接在一起并生成内核文件

标签:Lecture3,操作系统,Calls,MIT6,应用程序,mode,内核,CPU,内存
From: https://www.cnblogs.com/jll133688/p/18147464

相关文章

  • MIT6.S081 - Lab1: Xv6 and Unix utilities
    Part1:sleep实验要求与提示可以参考user/echo.c,user/grep.c和user/rm.c文件如果用户忘记传递参数,sleep应该打印一条错误消息命令行参数传递时为字符串,可以使用atoi函数将字符串转为数字使用系统调用sleep,有关实现sleep系统调用的内核代码参考kernel/sysproc.c(......
  • MIT6.S081 - Lecture1: Introduction and Examples
    课程简介课程目标理解操作系统的设计和实现通过XV6操作系统动手实验,可以扩展或改进操作系统操作系统的目标Abstraction:对硬件进行抽象Multiplex:在多个应用程序之间共用硬件资源Isolation:隔离性,程序出现故障时,不同程序之间不能相互干扰Sharing:实现共享,如数据交互或协......
  • pytorch报错:Variable._execution_engine.run_backward( # Calls into the C++ engine
    GPU模式下运行pytorch代码报错,pytorch为2.2.1,NVIDIA驱动版本535.161.07File"/home/devil/anaconda3/envs/sample-factory/lib/python3.11/site-packages/torch/_tensor.py",line522,inbackwardtorch.autograd.backward(File"/home/devil/anaconda3/envs/sample-......
  • MIT6.830-Lab5
    simpleDB项目地址概览类概述BTreePage:B+树节点(叶子节点和内部节点)的公共父类,存储了父节点页号protectedintparent,并且使用protectedfinalintkeyField存储在表记录的哪个字段建立索引。BTreeLeafPage:B+树的叶子节点,用来存放具体的表记录。BTreeInternalPage:B+树的内部节......
  • MIT6.830-Lab3
    simpleDB项目地址概览IntHistogram作用估计条件过滤某表的某个Int字段时,结果集记录数和该表记录总数的比例;StringHistogram类似IntHistogramTableStats作用存放某表各个字段对应的直方图对象(IntHistogram或StringHistogram类型);使用静态对象ConcurrentMap<String,Tab......
  • MIT6.830-Lab2
    simpleDB项目地址实验部分实验1Predicate类用来存放对表记录进行条件过滤的信息(要过滤字段的序号,具体的比较规则,用来比较的字段),其内部的枚举类Op就是比较规则类,filter()方法的实现使用Field接口中的compare()即可。JoinPredicate类用来存放两表的记录进行连接的信息(两表......
  • 【XV6】 system calls
    代码:https://github.com/JasenChao/xv6-labs.git使用GDB调试安装risc-v的GDB先安装依赖:sudoapt-getinstalllibncurses5-devpython2python2-devtexinfolibreadline-dev再下载源码,可以从清华镜像源下载:wgethttps://mirrors.tuna.tsinghua.edu.cn/gnu/gdb/gdb-13.2.ta......
  • mit6.824lab2D-Debug记录
    1.死锁要提交快照的时候由于没有人取走applyCh通道里面的东西,导致死锁。具体解释:2D的测试代码中在日志达到一定大小时会调用snapshot,该函数需要申请rf.mu这个互斥锁。而在提交普通的日志条目时,错误地没有先释放锁,导致snapshot无法进行下去,相关的进程卡在rf.mu这个锁上,无法完成......
  • MIT6.830-Lab1
    TupleDesc类TupleDesc类用来存储表结构,使用静态内部类TDItem封装字段类型和字段名称。Tuple类Tuple类用来存储具体的数据行,使用Filed接口数组存放不同字段类型的数据,使用TupleDesc成员变量存放与该数据行关联的表结构信息,使用RecordId成员变量存放该数据行的行号和所处的数......
  • [MIT 6.S081] Lab: system calls
    Lab:systemcalls前言这次实验是实现内核中的两个syscall:trace和sysinfo。回顾一下第三节课,用户态的进程想要执行某个系统调用,例如exex(init,argv),首先会将init和argv的地址分别存放在a0和a1寄存器中,然后a7存放所要调用的系统调用,最后执行ecall。之后要结......