【6.828学习笔记】MIT6.828总结与归纳

mit是宏内核还是微内核?※分别说一下这两个的优缺点?你有了解混合内核吗,混合内核跟前面两个有什么区别?※

  • 828是宏内核,宏内核是把所有核心功能都装载到内核当中,例如内存管理、进程管理等待 这样子实现简单,调用方便,缺点就是功能全部糅杂到一起,如果内核中一个功能崩溃那么整体内核就不可用,维护困难。
  • 微内核有点类似微服务的思想,将多个功能分散开来形成独立的功能,通过最小化内核,将大部分功能实现在用户态,提高系统的可靠性和安全性,更有利于维护和管理。缺点就是:当功能繁多的时候,各个功能直接需要频繁的通信,会导致性能较差、复杂度提升。
  • 混合内核顾名思义就是从宏内核和微内核中做折中方案,例如windows 将重要的内存管理 等核心功能实现在内核中,将另外的功能以可插拔的形式实现为内核模块 运行在用户空间。

bios到kernel的启动过程是什么样的?,实模式和保护模式所做的操作有哪一些,转换后mmu的作用。

bios到kernel的启动过程为:

  1. 接通电源后,CPU开始执行BIOS的代码
  2. BIOS执行硬件的初始化,从设备中寻找可启动的设备,所以会找到磁盘
  3. 因为磁盘的第一个扇区装载的是引导类加载器,所以会把硬盘头一个扇区加载到内存0x7c00的地址处并对引导类加载器初始化
  4. 之后BIOS将CPU资源交给引导类加载器负责,引导类加载器就将内核的镜像(存在第二个扇区)加载至内存指定位置当中
  5. 此时CPU控制权继续转移到内核代码上,从此开始内核就真正被运行起来了

实模式和保护模式所做的操作:

  1. 实模式中负责初始化GDT表和IDT表(主要通过lgdt加载GDT表、lidt加载IDT表)
    • GDT是一张存储在内存中的表,用于描述操作系统的各种内存段的基址以及长度等信息,为了防止程序恶意的使用其他段,在保护内存中,每个进程存在一份LDT表,而LDT包含的段描述符又存在于GDT中。
    • IDT是一张存储在内存中的表,用于描述操作系统的各种中断以及处理函数,当发生中断时,CPU即可通过这张表找到对应的处理函数
  2. 将CS和DS段基址分别指向GDT中的 代码段 和 数据段
  3. 将CR0寄存器的PE(保护模式使能,也就是第1bit位 )位设置为1,表示CPU进入保护模式
  4. 在保护模式后,由于访问地址需要通过MMU的转换,所以必须要先设置好页表以及开启分页机制,此后便可真正访问到虚拟空间的内存
  • MMU的作用:用于处理CPU中的虚拟地址和物理地址之间的转换

MMU是如何实现内存地址转换的?

分页机制:内存会被划分为等大小的页(6.828是4KB),每个页都有单独对应的物理地址

地址转换:CPU执行命令时,会将虚拟地址发送到MMU当中,由MMU通过CR3寄存器获取当前进程的页表,然后通过高10位找到页目录中的页表,再通过中间10位找到页表中对应的页表项,接着利用最后的12位来查询页表项中的虚拟地址,虚拟地址上存着的是物理地址,从而获取到物理地址,若是不存在物理地址,则会触发page Fault,这时候会跳转到内核态中,执行对应的page_fault_handler函数并判断是否是在用户态的缺页异常:

  • 如果,则在页错误处理函数中通过pgdir_walk()函数,分配到一个物理页到错误虚拟地址上,接着更新页表。此时页表上导致缺页错误的虚拟内存已经成功映射上物理地址,则会将tf->eip(即中断返回地址)修改为对应的刚刚分配的物理地址,然后返回用户态。
  • 如果不是,则直接报错,结束进程的运行。

是如何进行虚拟内存管理的?虚拟内存的整体布局,你可以简略的描述一下吗?※

  • 是通过二级页表将虚拟内存空间映射到物理内存空间上,从而实现了进程内存隔离、内存保护等功能

  • 内存空间布局如下:

    /*       虚拟内存分布图: 
     * Virtual memory map:                                Permissions 权限
     *                                                    kernel/user 内核/用户
     *
     *    4 Gig -------->  +------------------------------+                 --+
     *                     |                              | RW/--             | 
     *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                   |
     *                     :              .               :                   |
     *                     :              .               :                   |
     *                     :              .               :                 4Gig-256MB
     *                     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| RW/--             |
     *                     |                              | RW/--             |
     *                     |   Remapped Physical Memory   | RW/--             |
     *                     |                              | RW/--             |
     *    KERNBASE, ---->  +------------------------------+ 0xf0000000      --+
     *    KSTACKTOP        |     CPU0's Kernel Stack      | RW/--  KSTKSIZE   |
     *                     | - - - - - - - - - - - - - - -|                   |
     *                     |      Invalid Memory (*)      | --/--  KSTKGAP    |
     *                     |            无效内存  (*)      |
     *                     +------------------------------+                   |
     *                     |     CPU1's Kernel Stack      | RW/--  KSTKSIZE   |
     *                     | - - - - - - - - - - - - - - -|                 PTSIZE 4MB 
     *                     |      Invalid Memory (*)      | --/--  KSTKGAP    |
     *                     |            无效内存  (*)      | 
     *                     +------------------------------+                   |
     *                     :              .               :                   |
     *                     :              .               :                   |
     *    MMIOLIM ------>  +------------------------------+ 0xefc00000      --+
     *                     |       Memory-mapped I/O      | RW/--  PTSIZE 4MB
     * ULIM, MMIOBASE -->  +------------------------------+ 0xef800000 上部由内核控制 下部由用户控制
     *                     |  Cur. Page Table (User R-)   | R-/R-  PTSIZE
     *    UVPT      ---->  +------------------------------+ 0xef400000
     *                     |          RO PAGES            | R-/R-  PTSIZE
     *    UPAGES    ---->  +------------------------------+ 0xef000000
     *                     |           RO ENVS            | R-/R-  PTSIZE
     * UTOP,UENVS ------>  +------------------------------+ 0xeec00000
     * UXSTACKTOP -/       |     User Exception Stack     | RW/RW  PGSIZE
     *                     |           用户异常栈          |
     *                     +------------------------------+ 0xeebff000
     *                     |       Empty Memory (*)       | --/--  PGSIZE
     *    USTACKTOP  --->  +------------------------------+ 0xeebfe000
     *                     |      Normal User Stack       | RW/RW  PGSIZE
     *                     +------------------------------+ 0xeebfd000
     *                     |                              |
     *                     |                              |
     *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *                     .                              .
     *                     .                              .
     *                     .                              .
     *                     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
     *                     |     Program Data & Heap      |
     *    UTEXT -------->  +------------------------------+ 0x00800000      --+
     *    PFTEMP ------->  |       Empty Memory (*)       |                 PTSIZE 
     *                     |                              |                   |
     *    UTEMP -------->  +------------------------------+ 0x00400000      --+
     *                     |       Empty Memory (*)       |                   |
     *                     | - - - - - - - - - - - - - - -|                   |
     *                     |  User STAB Data (optional)   |                 PTSIZE
     *    USTABDATA ---->  +------------------------------+ 0x00200000        |
     *                     |       Empty Memory (*)       |                   |
     *    0 ------------>  +------------------------------+                 --+
    

    简述:虚拟内存空间主要分为两大部分,一部分是(ULIM,4Gig)这块内存空间,是只允许内核态读写的,不允许用户态有权限操作。而剩下的[0,ULIM]有980,992个PGSIEZ,专门为用户准备的

    1. 第一个PGSIZE(MMIOLIM,KSTACKTOP]主要用于CPU的内核栈,每个CPU都拥有一个内核栈,只允许内核读写
    2. 第二个PGSIZE(ULIM,MMIOLIM]保留I/O设备映射使用的内存区域
    3. 第三个PGSIZE(UVPT,MMIOBASE]是当前使用的页表的区域,内核用户都只读不可写,MIT6.828一个页表正好4MB大小。
    4. 第四个PGSIZE(UPAGES,UVPT]是页面结构的只读区域,内核和用户都只读不可写
    5. 第五个PGSIZE[UTOP,UPAGES]是进程结构的只读区域,内核和用户都只读不可写
    6. 第六、七个PGSIZE[USTACKTOP,UXSTACKTOP]是用户异常栈,内核和用户都可以读写,当超过USTACKTOP之后就代表栈溢出了,注意:栈是向下延伸的
    7. (USTABDATA,UXSTACKTOP]的空间都是用户存放数据的地方,这个地方简称为:堆(可以类比Java的堆)
    8. [0,USTABDATA]之间的代表NULL值,因为内存低区都默认为不可用的状态。

你的内存管理粒度是多大,如何对进程进行内存分配和管理。

MIT6.828中的内存粒度是页,一个页的大小为4KB

内存分配通过page_alloc函数,这个函数从page_free_list取出一个物理页,并返回页面起始地址

内存管理通过一个页结构(PageInfo)中的pp_ref计数为0时,代表已经没有引用指向这个物理页了,那么就可以通过page_free函数进行回收

还有page_insert函数是负责将一个物理页面插入到页表中,建立于虚拟地址映射,而page_lookup函数则是从页表中进行寻找对应的页表项,并返回相应的物理页。

通过以上函数来实现了内核对内存进行分配、回收、查询等操作

进程和线程有什么区别?※ 你进程中和线程中切换过程可以说一下吗?他们有什么区别?哪个开销更大,为什么?※

进程和线程区别:进程是操作系统分配的基本单位,而线程是操作系统调度的基本单位。多个线程共享同一个地址空间和其他资源。因此,创建和销毁进程的开销通常比创建和销毁线程的开销大。但是,由于线程共享同一个地址空间和其他资源,线程之间的切换开销比进程之间的切换开销要小。同时,多线程程序也可以更好地利用多核CPU的并行性能,提高程序的执行效率。

很遗憾,MIT6.828中没有提到线程的概念,只有进程。在6.828中实现进程的调度方式主要是轮询的方式,轮循到每一个进程都会分配对应的时间片。

你引入了多cpu,是如何进行调度? ※可以说一下你了解到其他的调度算法吗,它们各自的优缺点是什么?※

是时间片调度的。在MIT6.828中,每个CPU都有一个本地APIC,用于处理处理器间和处理器本地的中断。定时器中断是通过本地APIC的计时器定期产生的。当定时器中断发生时,本地APIC会发送一个中断给当前CPU,当前CPU会在中断处理程序中检查就绪队列,并根据调度算法选择新的进程开始执行。

其他的调度算法:

  • 先来先服务调度算法:按照顺序执行,**优点:**简单直接,**缺点:**如果长作业在短作业前面,那么短作业无法及时得到反馈,效率低下,平均等待时间长。
  • 短作业调度算法:按照执行的时间的长短执行,**优点:**短作业能被优先处理 **缺点:**很可能会造成饿死现象
  • 优先级调度算法:按照作业的优先级大小执行,**优点:**适合对付紧急情况 **缺点:**同样会造成饿死现象
  • 时间片调度算法:每一个作业被分配一个时间片,当使用完毕后放入队列中进行等待,**优点:**可以保证每一个作业都能被执行, **缺点:**时间片大 浪费性能,时间片小,作业之间的切换也会浪费性能,对于长作业而言尤其明显
  • 多级反馈队列调度算法:分为多个队列,每个队列具备不同的优先级,作业被放入哪一个队列中主要取决于执行时间和等待时间。**优点:**每一个作业都能被很好的处理,性能利用得均衡,不会有饿死现象 **缺点:**实现起来复杂

文件系统的管理是如何实现的

MIT6.828文件系统结构把硬盘分成大小相等的块,每个块都有对应的块号且块大小为4KB。

磁盘文件系统结构:

  • 块0不使用,因为上面存放着引导类加载器和分区表。

  • 块1为超级块,存放着文件系统属性的元数据,例如:块大小、磁盘大小等

  • 块2为块位图,因为每个块都有块号并单调递增的,所以通过位图上的bit位来判断是否为空闲状态。1为空闲,0为被使用

  • 此后所有的块是用于存储文件数据或目录的。

文件系统常用的操作有:磁盘块创建、磁盘块删除、磁盘块查找、文件查找

分配是通过alloc_block函数实现的,通过轮询的查找位图,获取第一个空闲的块,并返回对应的块号

删除是通过free_block函数实现,通过位图的方式,将对应bit位置为 1

查找是通过file_get_block函数实现,通过调用了file_block_walk函数,获取对应块号的地址后装入传参的**blk。

文件查找是通过dir_lookup函数实现,通过调用了file_get_block函数获取到传参dir中的所有块,然后去比对块中file.f_name是否与传参的name一样

你使用的是时间片调度,具体的流程是什么样的?你知道时间片是如何校准时间的吗。

流程:时间片是通过时钟中断来实现的。在MIT6.828中当时钟中断发生时,会调用对应的中断处理函数。具体实现在trap.c文件下的trap_dispatch(),这个函数就是负责当时间片用完后,调度下一个可运行的进程。

校准时间主要是通过kern/lapic.c中的lapicw(TICR, 10000000);, 表示设置 lapic[TICR] 为10000000。TICR是 APIC 定时器计数器寄存器,当CPU将lapic[TICR]减至为0后,就会触发定时器中断。

解释一下fork,有实现COW(写时复制)吗?这个你是怎么实现的?※怎么判断那一内存区域是需要COW的?COW的好处是什么※

fork是创建出子进程,该子进程与父进程共享同一个进程空间(虚拟内存空间),父进程中返回子进程的PID,而子进程会返回0。

有实现COW,子进程被创建之后,首先的操作就是把父进程的页表完全映射过来并不会完全复制。如果某个地址中权限位表示为可写(PTE_W)可写时复制(PTE_COW),那么就可以将此虚拟地址标记上写时复制并映射到子进程页表上。

COW 技术的好处在于节省了内存空间,因为父进程和子进程之间共享页面,而不是将整个空间复制一份,这样可以节省内存空间,提高系统的效率和性能

MIT6.828的fork函数流程:

首先会将页错误的处理程序设置为:异常处理函数pgfault,如果当发生写的情况,那么就会中断进行这个函数,pgfault会分配出一个页面专门对应父/子进程进行写入

接着,会调用sys_exofork来创建一个新的进程。

接下来sys_exofork中就会返回不同的值,0代表目前的进程是子进程,而>0的代表目前的进程是父进程

如果当前进程是子进程,那么则会将当前的进程thisenv首先标识为子进程

如果是父进程,那么就会将自身页表中所有的地址,通过duppage函数进行映射。具体映射操作:

会检查当前页表项是否存在,即PTE_P存在,不存在直接panic否则继续:

  • 会判断此页表项是否为共享,即PTE_SHARE存在,则直接映射
  • 会判断此页表项是否为可写或者写时复制,即PTE_W 或PTE_COW 存在,则将PTE_COW映射到子进程的页表项上同时重新映射到自己的页表项上(因为父子进程必须都要标识PTE_COW位,不然可能无法触发写时复制!这里我在实验中就踩坑了)

页表映射完后,则还会为子进程在UXSTACKTOP - PGSIZE创建一个页面作为异常栈。

最后同样将pgfault设置到子进程中的页错误处理函数,并将子进程设置为可运行的状态。

进程间如何通信?讲一讲其中最简单的管道通信的原理

操作系统中进程间的通信有以下几种方式:

  1. 匿名/有名管道,匿名管道会将数据存在内存当中,而有名管道会将数据存在硬盘当中。匿名管道只用于父子进程,而有名管道用于任意进程之间

    • 原理:父进程创建匿名管道,通过pipe()函数返回两个文件描述符,其中fd[0]用于读端,fd[1]用于写端。父进程调用fork()函数之后会创建出子进程,子进程会继承父进程的所有内存空间,同样也拥有了管道的读写端,但父进程会关闭读端,子进程会关闭写端。这样父进程就可以通过写端写入数据到管道中,而子进程就可以通过读端获取父进程的数据了。当数据传输完毕后,父进程会关闭管道的写端,那么此时子进程通过读端读取到返回值0,代表已经没有数据了,同样会关闭管道的读端,于是子进程结束。如果往后父进程再想通过写端进行写入时,那么就会收到SIGPIPE的信号,表示管道已经关闭了。
  2. 消息队列,由于管道是半双工方式管道的消息传输的效率是很低的,必须要建立两个管道才能实现全双工,所以引出了消息队列,消息队列可以实现全双工模式。但是消息是需要双方规定好消息格式的,并且消息的发送需要从用户态拷贝到内核态的缓冲区,再从内核态的缓冲区拷贝到用户态,会产生额外的开销。

  3. 共享内存,多个进程共享同一片物理内存区域,若要发生多进程同时写入场景,可以采用信号量或者写时复制解决。

    • MIT6.828当中是会通过sys_page_map()来映射物理页面的,这样多个进程都能跟共享同一份物理页面。
  4. 信号量,用来同步多个进程访问同一个内存区域。

    • 原理:本质是一个计数器,当一个进程要访问共享资源时,>0时代表此内存区域可访问,当<=0时代表无法访问。
  5. 信号,是一种软件中断,主要用在异常情况下,它是可以异步的,不需要接收方和放松方有相互作用。

  6. socket,不同主机间的进程通讯。

接下来是高端内存区域是什么地方?用来干什么的?访问高端内存区域会发生什么?(题主答:触发异常进内核态然后找对应函数去处理。为什么能够触发异常,想了想觉得应该是由页表项的后12位中有具体的权限门,锁死了用户态的访问。)

高端内存区域是[ULIM, 2^32),此256MB的内存区域只允许内核读写,用于内核存放数据,相当于内核专用的堆。如果当用户进程去访问这些高端区域,那么会发生异常,紧接着会进入对应的异常处理函数当中。

你项目中哪里有使用到锁?用到了哪种锁?※它们在这个项目中作用是什么?你可以讲讲项目种用到的锁的实现原理吗?※**

当进程进出内核态时需要使用内核锁。

项目中用到了内核锁kernel_lock,底层是通过自旋锁spinlock实现的,而自旋锁采用了CAS的思想,通过xchg指令实现,可以保证原子性。

内核锁,lock_kernel() 函数是 MIT 6.828 操作系统中用于获取内核全局锁的函数。它的作用是防止多个 CPU 同时修改内核数据结构和内存信息,保证内核代码的原子性和正确性。

xchg()的实现原理是通过总线锁定(Bus Lock)来保证原子性,总线锁定会在多处理器环境下把总线锁住,防止其它处理器访问共享内存,从而保证了对共享内存的原子操作。

XV6思维导图

启动流程:

[外链图片转存中...(img-pjjlLwzm-1680329767186)]

中断流程:

[外链图片转存中...(img-81VFYJzv-1680329767187)]

文件系统流程:

[外链图片转存中...(img-CLyiKuXx-1680329767187)]

如有错误,欢迎指正!

MIT 6.828是一门关于xv6操作系统的课程,该课程提供了关于xv6操作系统的中文指南和实验室。 xv6是一个操作系统的教学版本,MIT 6.828课程提供了xv6全文的翻译成书供学习使用。 在课程中,还提供了一些实验,供学生进行实践和学习。 关于xv6的具体实现细节,根据引用中的内容,在user.h文件中可以找到函数的定义。需要在date.c的代码中补充相应的函数。 另外,引用中提供了一个样例过程,展示了一系列操作的执行顺序,包括fork、exec、open、close、write等。这个样例过程可以帮助理解xv6操作系统的运行机制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [MIT-6.828:MIT 6.828操作系统课程](https://download.csdn.net/download/weixin_42139357/15728097)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [MIT6.828 Homework3 xv6 system calls](https://blog.csdn.net/qq_43012789/article/details/107746030)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值