BUAA-OS-2023-Lab5-Report
BUAA-OS-2023-Lab5-Report
Thinking 5.1
- 如果通过kseg0 读写设备,那么对于设备的写入会缓存到Cache 中。这是一种错误的行为,在实际编写代码的时候这么做会引发不可预知的问题。请思考:这么做这会引发什么问题?对于不同种类的设备(如我们提到的串口设备和IDE 磁盘)的操作会有差异吗?可以从缓存的性质和缓存更新的策略来考虑。
如果使用 kseg0 段读写设备,那么对于外设而言,在系统读取外设时就会不可避免地先在 Cache 中查找设备对应的地址,如果查询到就会返回缓存的值。但如果在上一次缓存过后,设备的值已经发生了改变,这时我们从 Cache 中读取到的就是过时的错误信息。
对于写入也是同理,我们会优先写入到 Cache 中对应的地址处,那么下一次写就会覆盖上一次写的结果,导致外设并不能及时、正确地读取到我们写入的值。
对于不同的外设种类而言,这个现象会有些微差异。串口设备由于其即时性与高使用频率,会更容易出现这样的错误,对于磁盘而言则不太容易。
Thinking 5.2
- 查找代码中的相关定义,试回答一个磁盘块中最多能存储多少个文件控制块?一个目录下最多能有多少个文件?我们的文件系统支持的单个文件最大为多大?
首先根据定义 BY2BLK
可知一个磁盘块大小为 4096 Byte。同时一个文件控制块 File
大小为 256 Byte。则一个磁盘块中最多能存储 $4096 / 256 = 16$ 个文件控制块。
一个目录可以通过 f_indirect
字段指向 1024 个指向其内包含的磁盘块的指针,那么一个目录下最多有 $1024 * 16 = 16384$ 个文件。
对于单个文件也是同理,f_indirect
字段会指向 1024 个包含其内容的磁盘块指针,这样一个文件最大大小就是 $1024 * 4KB = 4MB$
Thinking 5.3
- 请思考,在满足磁盘块缓存的设计的前提下,我们实验使用的内核支持的最大磁盘大小是多少?
由于 MOS 中一个进程可以拥有 4 GB 的虚拟内存空间,并且对于文件管理进程而言, DISKMAP
到 DISKMAP + DISKMAX
这一段虚存地址空间 (0x10000000-0x4fffffff) 会作为作为磁盘块的缓冲区。那么最大的磁盘大小就是 DISKMAP
,即 1 GB。
Thinking 5.4
- 在本实验中,fs/serv.h、user/include/fs.h 等文件中出现了许多宏定义,试列举你认为较为重要的宏定义,同时进行解释,并描述其主要应用之处。
其实文件控制块和超级块都比较好理解
struct File { //文件控制块,是文件系统用于管理文件的数据结构 |
// fsreq 的请求分类 |
//fs/serv.c |
这里就是我们进行ipc通讯后,对数据进行分发的场所,我们会根据收获到的req的不同,将用于接受信息(文件系统接受,由用户发来)的REQVA解读为不同的结构体,并传入不同的服务函数进行实现。
整个分发实现是文件系统与外界的接口,文件系统内部的实现是相对自由的(你可以进行系统调用、使用用户态函数、操作磁盘等等),只要反馈给用户进程的结果对就行
Thinking 5.5
- 在 Lab4 “系统调用与 fork” 的实验中我们实现了极为重要的 fork 函数。那么 fork 前后的父子进程是否会共享文件描述符和定位指针呢?请在完成上述练习的基础上编写一个程序进行验证。
// code here |
显然,父子进程也会同样共享相同的文件描述符和定位指针。其原因在于页面是 PTE_LIBRARY
的而非 PTE_COW
的。
Thinking 5.6
- 请解释 File, Fd, Filefd 结构体及其各个域的作用。比如各个结构体会在哪些过程中被使用,是否对应磁盘上的物理实体还是单纯的内存数据等。说明形式自定,要求简洁明了,可大致勾勒出文件系统数据结构与物理实体的对应关系与设计框架。
struct Fd { //文件描述符;用户用于描述该文件,单纯的内存数据,关机就消失; |
- 这部分的部分内容借鉴了学长的报告
Thinking 5.7
- 图 5.7 中有多种不同形式的箭头,请解释这些不同箭头的差别,并思考我们的操作系统是如何实现对应类型的进程间通信的。
- 同步消息,用黑三角箭头搭配黑实线表示:
同步意义:消息的发送者把进程控制传递给消息的接收者,然后暂停活动,等待消息接收者的回应消息。
返回消息,用开三角箭头搭配黑色虚线表示:
返回消息和同步消息结合使用,因为异步消息不进行等待,所以不需要知道返回值。
对于文件系统,通过特定调用号使得文件系统知道请求者有何种需求,然后文件系统进入相应处理函数中处理,将结果通过ipc_send传回用户进程。
小结
纵观 Lab5,MOS 在其中为我们构造了一个通配的文件系统。
它通过统一的结构体 Fd
层次化地管理所用可用的设备。向上,在 fd.c
中为用户提供统一的操作函数;向下,不同设备通过 implements 实现 Dev
的功能函数,达到同一调用的效果。
在此之下,file.c
、console.c
、pipe.c
三文件实现了 Dev
中的”抽象函数“。为了优化函数实现的效果,我们建立了一个为所有进程管理纯文件 file 的文件服务进程 serv.c
,并通过 fsipc.c
借助 进程间 IPC 通信机制实现数据传输。
对文件服务进程而言,它通过 IPC 通信与用户进程(请求方)通信,利用文件级、磁盘块级的交互函数 fs.c
与磁盘进行交互,并利用块缓存的机制对磁盘块进行管理,以满足请求者对指定文件的特定文件块的访问。
再细化到最后一步,所有的磁盘交互函数都是利用系统调用访问 KSEG1
段实现与外设的直接交互,并在最底层的函数中实现了以块、甚至扇区为单位的读写,即 ide.c
。