exam
往年的lab4上机分为4-1和4-2两个部分。
其中lab4-1侧重于考察系统调用本身的实现,而lab4-2仍以系统调用为载体,但更多地强调像fork一样,借助系统调用去实现某些功能。
对于本次上机:
在上机伊始,助教便提醒:
本次上机exam难度较易,请多用心挑战extra题目。
我认为主要原因是lab4的拆分,从而导致某些必考考点在简单的exam里得不到充分的测试。
本次exam共两项内容。
sys_get_ppid
得到当前进程的父进程的env_id,若没有父进程则返回0.
他甚至连try(envid2env(id, &e, 0))都不让你写,只需返回curenv的env_parent_id
至于没有父进程则返回0
这一点不必担心,此时env_parent_id也就是0.
因此最耗时的地方反而是更改这些:
include/syscall.h 扩充enum
include/error.h 扩充新的error
kern/syscall_all.c 扩充syscall_table
user/include/lib.h 函数声明
user/lib/syscall_lib.c 用户sys调用msys (这个有的时候有些门道,不仅仅是return msys那么简单)
PTE_PROTECT
在fork的duppage中额外考虑PTE_PROTECT
题意也很明白:若权限位含PTE_PROTECT(注意是不为0
),直接终止duppage函数。
也即在duppage函数中:
1
2
3
4
5
6
7
|
/* Hint: The page should be first mapped to the child before remapped in the parent. (Why?)
*/
/* Exercise 4.10: Your code here. (2/2) */
if ((perm & PTE_PROTECT) != 0) {
return;
}
if (((perm & PTE_D) == 0) || (perm & PTE_LIBRARY) || (perm & PTE_COW)) ...
|
至于PTE_PROTECT怎么来的,都不关我们的事。
大家这一题做的都很快,因为根本没有卡人的地方。
extra其实也是一道比较简单的题。但正因为题面简单,导致题干的提示少了一点,容易让自己瞎想。
在大多数人都轻松做对extra的时候,笔者又一次拿了0分。
比较搞笑的是,犯这样错误的人还不少。
原因是一个struct Shm shm_pool[];
大家总是要写shm_pool[key].npage等这样的信息,有些烦躁,就直接
struct Shm shm = shm_pool[key];
被面向对象宠坏了的同学们,完全没有想到这里已经不再是对象了。而是一个新的被赋了初值的变量
。
这里应当采用 struct Shm* shmptr = &shm_pool[key];
题面
见:
1
|
https://demiurge-zby.github.io/p/%E5%8C%97%E8%88%AAos-lab4-%E4%B8%8A%E6%9C%BA/lab4_extra.pdf
|
代码
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
struct Shm shm_pool[N_SHM];
int sys_shm_new(u_int npage) {
if (npage == 0 || npage > N_SHM_PAGE) {
return -E_SHM_INVALID;
}
// Lab4-Extra: Your code here. (5/8)
int id;
for (id = 0; id < N_SHM; id++) {
if (shm_pool[id].open == 0) {
shm_pool[id].npage = npage;
/* 太蠢了太蠢了太蠢了!!!*/shm_pool[id].open = 1;// 笔者的核心错因是忘记写这句话!!!!!!!
for (int i = 0; i < npage; i++) {
int r;
struct Page* pp;
r = page_alloc(&pp);
if (r < 0) {
shm_pool[id].npage = 0;
shm_pool[id].open = 0;
for (int j = 0; j < i; j++) {
page_decref(shm_pool[id].pages[j]);
shm_pool[id].pages[j] = NULL;
} return -E_NO_MEM;
}
shm_pool[id].pages[i] = pp;
pp->pp_ref++;
} return id;
}
}
return -E_SHM_INVALID;
}
int sys_shm_bind(int key, u_int va, u_int perm) {
if (key < 0 || key >= N_SHM) {
return -E_SHM_INVALID;
}
// Lab4-Extra: Your code here. (6/8)
if (shm_pool[key].open == 0) {
return -E_SHM_NOT_OPEN;
}
u_int addr = va;
for (int i = 0; i < shm_pool[key].npage; i++) {
page_insert(curenv->env_pgdir, curenv->env_asid, shm_pool[key].pages[i], addr, perm);
addr += PAGE_SIZE;
}
return 0;
}
int sys_shm_unbind(int key, u_int va) {
if (key < 0 || key >= N_SHM) {
return -E_SHM_INVALID;
}
// Lab4-Extra: Your code here. (7/8)
if (shm_pool[key].open == 0) {
return -E_SHM_NOT_OPEN;
}
u_int addr = va;
for (int i = 0; i < shm_pool[key].npage; i++) {
if (shm_pool[key].pages[i] == NULL) break;
page_remove(curenv->env_pgdir, curenv->env_asid, addr);
addr += PAGE_SIZE;
}
return 0;
}
int sys_shm_free(int key) {
if (key < 0 || key >= N_SHM) {
return -E_SHM_INVALID;
}
// Lab4-Extra: Your code here. (8/8)
if (shm_pool[key].open == 0) {
return -E_SHM_NOT_OPEN;
}
shm_pool[key].open = 0;
for (int i = 0; i < shm_pool[key].npage; i++) {
page_decref(shm_pool[key].pages[i]);
}
return 0;
}
|
后记
这次上机exam大多数同学在20min以内都能完成。
但是如此简单的extra,是如何让大家虚空debug 100min 的呢?
我的vim出现了一次很可怕的问题。在粘贴之后,一些奇怪的位置也被粘贴了那段代码。整个syscall.c都被毁了,于是从OS gitlab里重新复制代码粘了上去。
这可能浪费了一点时间?
此外,lab3-exam告诉我们不要太高估exam,lab4-extra则告诉我们不要太高估extra!
这句话有点太狂妄了() 但是希望大家做题的时候千万不要想太多! 必须实现的奇思妙想一定会在HINT里指出!!!
由于题目里告诉我们可以用page_remove来实现shm_unbind,却没有明确指出用page_insert来实现shm_bind。
我便一口认定要自己重新手搓shm_page_insert函数。后面的一切努力当然都是徒劳。
怎么能忘记把open置1啊?!!
宛如曾经P6上机循环没有变量初始化、忘记写[31:0]一般的无力感
哦对!今天是我的生日!生日快乐!祝大家都要快乐!!!