Lab5实验报告

Lab5实验报告

一、思考题

Thinking 5.1

查阅资料,了解 Linux/Unix 的 /proc 文件系统是什么?有什么作用? Windows 操作系统又是如何实现这些功能的?proc 文件系统这样的设计有什么好处和可以改进的地方?

/proc文件系统是一个虚拟文件系统,它只存在内存当中,而不占用外存空间。

Linux内核提供了一种通过/proc文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。(参考网上资料)

windows系统中是通过Win32 API函数的调用完成与内核的交互的。

/proc文件系统的设计将对内核信息的访问交互抽象为对文件的访问修改,简化了交互过程。

Thinking 5.2

如果我们通过 kseg0 读写设备,我们对于设备的写入会缓存到 Cache 中。通过 kseg0 访问设备是一种错误的行为,在实际编写代码的时候这么做会引发不可预知的问题。请你思考:这么做这会引起什么问题?对于不同种类的设备(如我们提到的串口设备和 IDE 磁盘)的操作会有差异吗?可以从缓存的性质和缓存刷新的策略来考虑。

可能会导致访问错误。kseg0是存放内核的区域,通过cache访问,但是如果在写入设备时将写入缓存到cache,就会导致想访问内核时,错误的访问cache中写入的内容。

对不同种类的设备的操作会有差异。比如串口相对于IDE磁盘速度会更快,所以操作串口时要提高刷新的频率。而IDE涉及到多个线路的数据冲突问题,操作会更为复杂。

Thinking 5.3

比较 MOS 操作系统的文件控制块和 Unix/Linux 操作系统的 inode 及相关概念,试述二者的不同之处。

MOS操作系统的文件控制块是将文件名和文件物理地址一同放入文件控制块中。

Unix/Linux操作系统的inode是索引节点,用来存放档案及目录的基本信息,为了提高索引的速度,Unix/Linux只将文件名与指向inode的指针放入目录项里面,但是文件的物理地址 放在了inode里,这一点和MOS操作系统有差别。

Thinking 5.4

查找代码中的相关定义,试回答一个磁盘块中最多能存储多少个文件控制块?一个目录下最多能有多少个文件?我们的文件系统支持的单个文件最大为多大?

一个磁盘块中最多能存储16个文件控制块。

一个目录下最多能有1024*16=16384个文件。

我们的文件系统支持的单个文件最大为1024*4KB = 4MB

Thinking 5.5

请思考,在满足磁盘块缓存的设计的前提下,我们实验使用的内核支持的最大磁盘大小是多少?

最大磁盘大小是0x6f3fd000

Thinking 5.6

如果将 DISKMAX 改成 0xC0000000, 超过用户空间,我们的文件系统还能正常工作吗?为什么?

不能正常工作。

因为这样的话会导致缓存磁盘块将内核的内容覆盖掉,从而导致异常,文件系统就无法正常工作。

Thinking 5.7

在 lab5 中,fs/fs.h、include/fs.h 等文件中出现了许多结构体和宏定 义,写出你认为比较重要或难以理解的部分,并进行解释。

我认为比较难理解的部分主要是几个宏定义部分,如下:

#define BY2BLK BY2PG //相当于一个磁盘块的大小,在大小上等于一页的大小

#define BIT2BLK (BY2BLK*8) //将单位从字节转化为位,因为位图法记录一个磁盘块是否被被分配出去只需要1位

#define BY2FILE 256 //记录一个文件控制块的大小

#define FILE2BLK (BY2BLK/sizeof(struct File)) //记录一个磁盘块能存放的文件控制块的个数,当需要遍历磁盘块中的所有文件时使用它
Thinking 5.8

阅读 user/file.c,你会发现很多函数中都会将一个 struct Fd* 型的 指针转换为 struct Filefd* 型的指针,请解释为什么这样的转换可行。

可以观察得出,两个结构体的定义如下:

第一个是:

 struct Fd {
     u_int fd_dev_id;
     u_int fd_offset;
     u_int fd_omode;
 };

第二个是:

 struct Fd {
     u_int fd_dev_id;
     u_int fd_offset;
     u_int fd_omode;
 };

由以上对比可以看出,Filefd结构体的第一个成员就是Fd,所以经过强制转换之后,指向Filefd的指针同样指向Fd的起始位置,并没有造成错误,所以转换可行。

Thinking 5.9

在lab4 的实验中我们实现了极为重要的fork 函数。那么fork 前后的父子进程是否会共享文件描述符和定位指针呢?请在完成练习5.8和5.9的基础上编写一个程序进行验证。

部分关键测试程序如下:

//省略若干宏定义

int main(void) {
    int fd = open("./test.cap", O_RDWR);
    if(-1 == fd) {
        printf("file openerror\n");
        return -1;
    }
    
    pid_t pid;
    
    if((pid = fork()) < 0) {
        printf("fork error");
    }else if(pid == 0) {
        printf("child\n");
        printFdInfo(fd);
        printf("chiled seek %d\n", lseek(fd, 3, SEEK_CUR));
        printf("child\n");
    }else {
        sleep(2);
		printf("child\n");
        printFdInfo(fd);
        printf("parent seek cur %d\n", lseek(fd, 0, SEEK_CUR));
        printf("child\n");
   	}
    
    return 0;
}

//省略printFdInfo函数,主要用于判断作用
Thinking 5.10

请解释Fd, Filefd, Open 结构体及其各个域的作用。比如各个结构体会在哪些过程中被使用,是否对应磁盘上的物理实体还是单纯的内存数据等。说明形式自定,要求简洁明了,可大致勾勒出文件系统数据结构与物理实体的对应关系与设计框架。

Fd结构体如下:

 struct Fd {
     u_int fd_dev_id; 
     u_int fd_offset;
     u_int fd_omode;     
 };

其中Fd用于记录文件的基本信息。其中的定义fd_dev_id指的是外设的idfd_offset指的是读写的偏移量,fd_omode指的是打开方式,包括只读、只写、读写等在内。

FileFd的结构体如下:

struct Filefd {
     struct Fd f_fd;
     u_int f_fileid;    
     struct File f_file; 
 };

其中FileFd用于记录文件的详细信息。其中的f_fd指的是file descriptorf_fileid指的是文件的idf_file指的是真正的文件本身。

Open的结构体如下:

 struct Open {
     struct File *o_file; 
     u_int o_fileid;     
     int o_mode;            
     struct Filefd *o_ff;  
 };

其中Open结构体是打开文件行为的抽象。其中的o_file指的是打开的文件的指针,o_fileid指的是打开的文件的ido_mode指的是打开方式,o_ff指的是指向读写位置的指针。

Thinking 5.11

UML时序图中有多种不同形式的箭头,请结合UML 时序图的规范,解释这些不同箭头的差别,并思考我们的操作系统是如何实现对应类型的进程间通信的。

黑三角箭头搭配黑实线表示的是同步消息,是消息的发送者把进程控制传递给消息的接收者,然后暂停活动等待回应;

两条小线的开箭头和黑色实线表示的是异步消息,不需要等待;

开三角箭头搭配黑色虚线表示的是返回消息,与同步消息结合使用的;

用开三角箭头搭配黑实线表示的是创建消息,其下面特别注明create

用黑三角箭头搭配黑实线表示的是摧毁消息,其下面特别注明destroy

操作系统利用env_ipc_recving实现进程的同步。

Thinking 5.12

阅读serv.c/serve函数的代码,我们注意到函数中包含了一个死循环for (; ; ) {…},为什么这段代码不会导致整个内核进入panic 状态?

serve在调用ipc_recv函数之后会将自身状态变为ENV_NOT_RUNNABLE,从而进入等待状态,它像一个后台程序,在其他进程发出文件系统请求后才被唤醒并开始服务,因此这段代码不会导致整个内核进入panic状态。

二、实验难点图示

文件系统层次关系

文件系统之间的逐级调用在我看来是比较难得一个地方:
在这里插入图片描述

文件系统有四个层次:用户接口,抽象层,具体实现,设备接口。

IDE磁盘驱动

关于驱动程序的编写需要知道我们都需要进行哪些操作:
在这里插入图片描述

文件系统用户接口

文件系统的用户请求IPC主要有以下几种:

#define FSREQ_OPEN	1
#define FSREQ_MAP	2
#define FSREQ_SET_SIZE	3
#define FSREQ_CLOSE	4
#define FSREQ_DIRTY	5
#define FSREQ_REMOVE	6
#define FSREQ_SYNC	7

操作如下:

在这里插入图片描述

三、体会与感想

lab5难度上比起lab4感觉小了一点,但是难度还是有的,代码量也比较大,总花费了两三天的时间。但是说实话lab5实验做到了十五周,感觉还是时间挺紧张的,毕竟最近一直在复习理论,所以实验也没有敢给太多的时间,这次的实验报告写的也比较草,因为时间真的不够了……

不过lab5的两次上机都还算有惊无险地过了,因为lab2挂的太惨了,所以导致最后离申优线还是有一定的差距,不过也不算遗憾啦,经过一学期的os学习,尤其是实验部分的学习,感觉自己代码水平相比大一时已经有了很大的进步了。

OS实验上机到此就圆满结束了,前期过的很艰难,但还好自己没有放弃,后来慢慢找到感觉了,写的也顺利了起来,之后还有lab6的部分,希望等到自己考完其他学科的考试再慢慢完成吧,很感谢助教gg们细心的指导与帮助,也很感谢身边一起分享bug的同学,6系是个很温暖的大家庭。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值