lab5挑战性任务

任务:
修改系统调用或编写新的系统调用,使得:
1. 只有文件系统进程能读写IDE磁盘
2. 文件系统新城仅能读写IDE磁盘而不能读写其他内核地址
选做部分:
用户态下使用writef函数经常出现输出到一半就被打断的情况,如何解决?

lab5挑战性任务-必做部分

任务分析

  1. 只有文件系统进程能读写IDE磁盘

由于文件系统进程使用固定的进程号标识,而IDE磁盘的读写只能通过syscall_read_devsyscall_write_dev两个系统调用来实现。所以只需要在系统调用时检查当前进程的进程号,如果是4097则正常执行,否则抛出异常

  1. 文件系统仅能读写IDE磁盘而不能读写其他的内核地址

通过grep "syscall_" -rn .检查文件系统fs中出现的系统调用

发现大致上可以分为两类,syscall_read_devsyscall_write_dev需要进一步的检测,其他的系统调用使用的va已经在对应的sys_xxx函数内部进行了检查所以不需要考虑。

通过grep发现syscall_read_devsyscall_write_dev只在ide.c中的ide_readide_write中被调用,而ide_readide_write只在fs.c中的write_blockread_block中被调用。

不难发现这两个函数中使用的va都是通过diskaddr得到的,因为该函数内部已经设有检查,所以不可能出现内核态的va。因此文件系统自身运行的过程中不会出现非法访问内核态的情况。只需要避免文件系统所在进程使用非法的系统调用即可。

新增内容

测试

  1. 其他进程读磁盘

  2. 其他进程写磁盘

测试代码

测试结果

  1. 文件系统进程读内核其他区域
  2. 文件系统进程写内核其他区域

测试代码

测试结果

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操作即可

正确结果

posted @ 2020-08-26 10:06  bl水滴  阅读(366)  评论(0编辑  收藏  举报