思考题
Thinking 5.1
kseg0 中有内核相关的各种数据如 pages 数组、envs 数组等,在kseg0中读写数据可能会对这些内容造成不赢的的修改。
向 cache 的写入会被缓存,直到 cache 缺失进行替换时才会执行写入,这对于一些输出外设如音箱和显示屏等会造成输出信息的大量延迟。类似的,cache 缺失造成的延迟也会拖慢外设输入后的计算机反应速度。
因此磁盘设备会更不容易出现错误,而外设会更容易出现错误。
Thinking 5.2
一个磁盘块大小为 BY2BLK = BY2PG = 4096。
一个文件控制块大小为 BY2FILE = 256。
一个磁盘块最多存储 BY2BLK / BY2FILE = 4096 / 256 = 16 个文件控制块。
按照 MOS 的简化存储方法,一个文件或目录恰好能存储一个磁盘块能装下的最大指针数量的磁盘块,即一个文件或目录下至多包含 BY2BLK / sizeof(uint32_t) = 4096 / 4 = 1024 个磁盘块。
因此单个文件最大大小为 1024 * BY2BLK = 1024 * 4KB = 4MB。
因此一个目录下至多有 1024 * BY2BLK / BY2FILE = 1024 * 16 = 16384 个文件。
Thinking 5.3
在 MOS 中,我们相当于将整个磁盘都映射到了虚拟内存空间内,因此最大瓷盘大小为 DISKMAX = 1GB。
Thinking 5.4
fs/serv.h
PTE_DIRTY 在页表项中的 ”磁盘脏” 标记,代表对应的磁盘块已经被修改但未写入磁盘
BY2SECT 单个磁盘扇区的大小(字节数),磁盘必须以扇区为单位读取
SECT2BLK 一个磁盘块内的扇区数目
DISKMAP 文件系统作为用户进程,其虚存空间的一部分与磁盘空间一一映射,该宏定义了映射的开始位置
DISKMAX 该宏定义了映射的总大小(即最大地址位置在 DISKMAP + DISKMAX)
user/include/fs.h
BY2BLK 单个磁盘块的大小(字节数),磁盘的文件管理以块为单位
BIT2BLK 单个磁盘块的大小(位数,比特数)
MAXNAMELEN 文件名的最长大小(char数)
MAXPATHLEN 路径名的最长大小(char数)
NDIRECT 文件直接指针数量
NINDIRECT 文件间接指针数量,由于 MOS 的简化保存法,实际为文件直接和间接指针总和,也即文件对应的最大块数
MAXFILESIZE 文件的最大大小,由 NINDIRECT * BY2BLK 算出
BY2FILE 文件控制块的大小(字节数)
Thinking 5.5
会共享。文件描述符本质上是内存中的变量,在fork后会复制同样的内容给父子进程,因此文件描述符是相同的。既然是相同的,对应的定位指针也会是同一个定位指针,因此父子进程会共享文件描述符和定位指针。
Thinking 5.6
struct Fd
为文件描述符结构体,为单纯内存数据,其中:
- u_int fd_dev_id 外设 id
- u_int fd_offset 读写的当前偏移量
- u_int fd_omode 文件打开方式,如只读
struct Filefd
为记录文件详细信息的结构体,为单纯内存数据,其中:
- struct Fd f_fd 对应的文件描述符
- u_int f_fileid 文件的 id
- struct File f_file 对应的文件系统控制块
struct File
为描述具体文件的结构体,对应磁盘上的物理实体,其中:
- char f_name[MAXNAMELEN] 文件名
- uint32_t f_size 文件大小,单位字节
- uint32_t f_type 文件类型,文件或目录
- uint32_t f_direct[NDIRECT] 文件直接对应的十个文件块指针
- uint32_t f_inidirect 文件间接对应的文件块指针所在的块
- struct File *f_dir 父目录
- char f_pad[略] 为了使 File 结构体恰好占用一定大小的 padding 部分
Thinking 5.7
分为两种,同步消息和返回消息。
同步消息以实心三角黑箭头+黑实线表示,消息的发送者会在消息发送后暂停活动,直到收到消息接受者的回应消息,才会继续运作。实现方式为先调用 ipc_send 发送消息后,再调用 ipc_recv 接收返回消息,接收到后才会继续运行。
返回消息以开三角箭头+黑虚线表示,代表消息的发送者只管发送,发送后继续进行自己的相关活动,不等待消息接收者的回应,常用于对同步消息的回应。实现方式为直接调用 ipc_send 发送消息即可。
难点分析
外设相关 syscall
主要是 Exercise 5.1~5.2 的部分,本身逻辑不难,按要求完成即可,难点在于判断允许访问的地址范围时需要仔细书写,尤其是不止要检测 pa 的范围,同样也要检测 pa+len 的范围。
ide
按照汇编代码类似的逻辑进行物理地址的书写即可,需要注意不能搞错 read 和 write。
create_file
需要仔细阅读 struct File 的定义,理解这里的关系。
fs.c
明确文件目录的结构关系以及内存使用即可。
open 函数
按照要求调用对应的函数即可。
read 函数
参考 write 即可。
实验体会
lab5 的实验并不是很难,但是需要对文件系统的一些思考和理解,虽然代码部分不难,但是具体到理解整个运作其实还是有一定难度的,需要仔细理解认知。