Featured image of post 北航OS Lab5 上机

北航OS Lab5 上机

OS上机的尾声

终于还是来到了最后一次上机。

可能是作为第一届拥有OS官方课下答案的试验品,同学们对OS整体架构的把握情况貌似远不如前。毕竟花的时间可能确确实实地少了。 我自己则更是深刻感受到与学长们的差距。直到上机,也还在疯狂地寻找结构体成员的名字是什么,找结构体在哪里宏定义,找各种各样的lookup,walk与get究竟要怎么用。

在上机前,我还在抱有幻想。我自以为对各种方法的基本功能不太陌生。给我一个方法名,我知道大概记得它能得到什么,它会改变什么。 但我并没有意识到我根本不会用。当我真的要填写参数的时候,这里要填谁?这个参数来源于谁?那个结构体成员变量名到底是谁?

exam

这次的exam我个人认为是不难的。尽管总共用了1个小时,中途de了很久bug,但是上完机和别人交流后发现花费1个小时貌似并不是特别长。

题面

见:

1
https://demiurge-zby.github.io/p/%E5%8C%97%E8%88%AAos-lab5-%E4%B8%8A%E6%9C%BA/lab5_exam.pdf

其实题目本身并不是很简单,但是给的提示太全面了。本来我看到深搜的时候有点慌,但是具体实现都已经给出来了。

基本上所有人在这里卡住,都只是把path与name拼接时出错。不过这也是这道题在给予如此多的提示之下最大的难点了。


不过,这个难点并不是很易于察觉。

注意到题干上明确指出了给出的path以’/‘结尾。 但是样例上在输出时却又发现结尾并不含’/’。

这意味着我们至少要做出一点改动: 要么保证所有的path都以’/‘结尾,但保存时要把最后一个’/‘变为’\0’ 如果保证path以’/‘结尾,在拼接时应当直接拼接name再加上’/’

要么就保证所有的path都不以’/‘结尾,保存时直接用path 这样的话,我们就需要在拼接时,先在path后追加’/’,再拼接name 但是刚开始的path是保证以’/‘结尾的,因此,在path后追加’/‘时,要先判断现在的结尾是不是’/’

这时有同学要说了:哎呀这也太复杂了吧,这怎么想得到呢?

为了让大家顺利通过,助教现场添加了一条又一条新的HINT,并疯狂地参与答疑。

最后的结果应当是不错的。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
int traverse_file(const char *path, struct File *file, const char *name, struct Find_res *res) {

	u_int nblock;
	nblock = file->f_size / BLOCK_SIZE;
//	debugf("now path is %s\n", path);
	// 1. 检查路径长度是否符合要求,如不符合,直接返回
	if (strlen(path) == 0 || strlen(path) > MAXPATHLEN/* path 的长度为零或不小于最大路径长度*/) {
		/*返回*/
		return;
	}

	// 2. 比较当前文件名是否等于 name,如果相等则更改 res
	if (strcmp(name, file->f_name) == 0/*file 的名字等于 name*/) {
	//	debugf("path is %s, name is %s\n", path, file->f_name);
		/*增加 res->count*/res->count++;
		/*添加 res 的路径*/strcpy(res->file_path[res->count - 1], path);
	}
	if (file->f_type == FTYPE_DIR) {
		for (int i = 0; i < nblock; i++) {
			void *blk;
			try(file_get_block(file, i ,&blk));
			struct File *files = (struct File *)blk;
			for (struct File *f = files; f < files + FILE2BLK; ++f) {
				char curpath[MAXPATHLEN + MAXNAMELEN + 3];
				// 3. 把 path 和 name 拼接起来得到下一层文件路径,注意结尾的 '\0'
				// 提示:我们没有实现 strcat 工具函数,你可以用 strcpy 实现拼接
				strcpy(curpath, path);
				if (curpath[strlen(curpath) - 1] != '/') {
					strcpy(curpath + strlen(curpath), "/\0");
				}
				strcpy(curpath + strlen(curpath), f->f_name);
				strcpy(curpath + strlen(curpath), "\0"); // 其实可以不需要
				// 4. 递归调用 traverse_file 函数
				traverse_file(curpath, f, name, res);
			}
		}
	}
	return 0;
}

int find_files(const char *path, const char *name, struct Find_res *res) {
        struct File *file;
	int r;
        // 用 walk_path 来找到 path 对应的文件夹
        // Lab5-Exam: Your code here. (1/2)
	if ((r = walk_path(path, 0, &file, 0)) < 0) {
		return r;
	} // debugf("I have found\n");
        // 在 path 对应的文件夹下面遍历,找到所有名字为 name 的文件,你可以调用下面的参考函数 traverse_file
        // Lab5-Exam: Your code here. (2/2)
	traverse_file(path, file, name, res);
	return 0;
}

extra

jby学长出的很有意思的综合性很强的加密文件extra。

其实流程给的也很详细了,奈何自己的熟练程度还是太差。

题面

见:

1
https://demiurge-zby.github.io/p/%E5%8C%97%E8%88%AAos-lab5-%E4%B8%8A%E6%9C%BA/lab5_extra.pdf

错误的代码

下面是我跟着流程,装模作样写出来的其中一个函数。其中很多用法自己也不确定,*(blk->data) != FS_MAGIC好像还编译错误了。(我还特意看了block的data是字节的指针呢。 哦,笔者刚刚意识到FS_MAGIC是字)

仅仅这么点看起来很公式,很平凡的代码,还充满了提示,我却足足用了半个多小时的时间。此时还有8个有流程的函数没有完成,还有serve_map与serve_close没有修改。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void serve_key_set(u_int envid, struct Fsreq_key_set *rq) {
  // 判断当前状态是否已加载密钥,如果已加载密钥, IPC 返回 -E_BAD_KEY
	if (encrypt_key_set != 0) {
		ipc_send(envid, -E_BAD_KEY, 0, 0);
		return;
	}
  // 利用 open_lookup 找到对应的 Open 结构体,判断文件大小是否至少有两个磁盘块大小
  // 利用 file_get_block 读取文件的第一个磁盘块,判断第一个字是否为 FS_MAGIC
  // 如果密钥文件不合法, IPC 返回 -E_INVALID_KEY_FILE
  	struct Open *o;
	if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}
	if (o->o_file->f_size < 2 * BLOCKSIZE) {
		ipc_send(envid, -E_INVALID_KEY_FILE, 0, 0);
		return;
	}
	struct Block *blk;
	if ((r = file_get_block(o->o_file, 0, &blk)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}
	if (*(blk->data) != FS_MAGIC) {
		ipc_send(envid, -E_INVALID_KEY_FILE, 0, 0);
		return;
	}
  // 利用 file_get_block 读取文件的第二个磁盘块,将密钥复制到 encrypt_key 中
	if ((r = file_get_block(pOpen->o_file, 1, &blk)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}
	strcpy(encrypt_key, blk->data);

  // 将当前状态标记为已加载密钥
	encrypt_key_set = 1;
  // IPC 返回 0
	ipc_send(envid, 0, 0, 0);
}

后记

OS上机结束了,回头看来,真是一无是处。曾经还在为lab0-extra懊悔不已,现在已经连连溃败。

OOhw13因为重构代码,漏了一句很重要的话,却没被中测测出来,导致强测完全失败,比hw7的分数还要低得多。

乒乓球也因为平时没有经常与老师交流,考试时错误频出,等待下周再次测试。

没几天就要去考OS理论期末了。准确来说,就是端午节假期后的第一个上午。本学期最高学分的课程就要结束了。

祝好运。

comments powered by Disqus
Easy Life and Easy Learning
使用 Hugo 构建
主题 StackJimmy 设计