lab5挑战性任务
任务:
修改系统调用或编写新的系统调用,使得:
1. 只有文件系统进程能读写IDE磁盘
2. 文件系统新城仅能读写IDE磁盘而不能读写其他内核地址
选做部分:
用户态下使用writef
函数经常出现输出到一半就被打断的情况,如何解决?
lab5挑战性任务-必做部分
任务分析
- 只有文件系统进程能读写IDE磁盘
由于文件系统进程使用固定的进程号标识,而IDE磁盘的读写只能通过syscall_read_dev
和syscall_write_dev
两个系统调用来实现。所以只需要在系统调用时检查当前进程的进程号,如果是4097则正常执行,否则抛出异常
- 文件系统仅能读写IDE磁盘而不能读写其他的内核地址
通过grep "syscall_" -rn .
检查文件系统fs中出现的系统调用
发现大致上可以分为两类,syscall_read_dev
和syscall_write_dev
需要进一步的检测,其他的系统调用使用的va已经在对应的sys_xxx
函数内部进行了检查所以不需要考虑。
通过grep发现syscall_read_dev
和syscall_write_dev
只在ide.c
中的ide_read
和ide_write
中被调用,而ide_read
和ide_write
只在fs.c
中的write_block
和read_block
中被调用。
不难发现这两个函数中使用的va都是通过diskaddr
得到的,因为该函数内部已经设有检查,所以不可能出现内核态的va。因此文件系统自身运行的过程中不会出现非法访问内核态的情况。只需要避免文件系统所在进程使用非法的系统调用即可。
新增内容
测试
-
其他进程读磁盘
-
其他进程写磁盘
测试代码
测试结果
- 文件系统进程读内核其他区域
- 文件系统进程写内核其他区域
测试代码
测试结果
lab5挑战性任务选做部分——使writef不被打断
错误样例及原因分析
通过调用fork分别让父子进程输出计数器的值,发现了writef被打算的情况
分析原因,可能是因为上一次writef还没有进行完就被打断,然后执行另一个进程的writef,从而使得输出结果被切分成了两部分
解决方法
受到理论课知识的启发,实际上出现问题是因为writef成为了一个临界区,所以只要给临界区加锁就可以保证一个进程的writef不会被打断(或者说即使被打断了,其他进程也会主动放弃cpu切换回来)所以我新写了三个系统调用实现了一个简单的信号量mutexWRITE
的PV操作以及初始化
int sys_P(void)
{
if (mutexWrite.value>1) panic("something wrong with mutex\n");
mutexWrite.value--;
if (mutexWrite.value>=0) return 0;
int count = mutexWrite.count;
if (count>=10) {
panic("too many env!\n");
}
mutexWrite.waitline[count] = curenv;
mutexWrite.count++;
curenv->env_status = ENV_NOT_RUNNABLE;
sys_yield();
}
int sys_V(void)
{
mutexWrite.value++;
if(mutexWrite.value>1) panic("something wrong with mutex\n");
if(mutexWrite.value == 1) return 0;
(mutexWrite.waitline[0])->env_status = ENV_RUNNABLE;
int i;
for(i = 0;i < mutexWrite.count - 1;i++) {
mutexWrite.waitline[i] = mutexWrite.waitline[i+1];
}
mutexWrite.count--;
sys_yield();
}
int sys_init(void)
{
mutexWrite.value = 1;
mutexWrite.count = 0;
return 0;
}
之后只需要在第一次执行writef的时候执行初始化操作,进writef进行P操作,结束writef进行V操作即可