nachos操作系统(七)

本节实现重新写内存分配管理。主要有两个知识点,一个是内存管理,一个是系统调用,现在先实现内存管理,然后实现系统调用,预计至多4个课时。

预计内存管理就是写比较简单的,系统调用都是这样预见的。

要实现内存管理,就要实现多道程序并行运行,不然内存管理没法测试,因此要先实现Exec。

userprog/syscall.h里面写的系统调用号为:

/* system call codes -- used by the stubs to tell the kernel which system call
 * is being asked for
 */
#define SC_Halt		0
#define SC_Exit		1
#define SC_Exec		2
#define SC_Join		3
#define SC_Create	4
#define SC_Open		5
#define SC_Read		6
#define SC_Write	7
#define SC_Close	8
#define SC_Fork		9
#define SC_Yield	10

而且在这个文件里,包括exec,join,fork,read等等耳熟能详的函数,系统调用接口,不过这是头文件,并没有它的详细实现,并且没有对应的源文件,大概率是让我们实现这个源文件。

文档中说,进程开启入口写在userprog/exception中的ExceptionHandler(ExceptionType which)函数里,这个which是一个中断性质的参数,被引入后,在SyscallException中实现进程开启,否则就是其他错误中断。

中断开启后,文档中说,我们需要指定一个文件,来运行文件,那么如何指定呢?在ExceptionHandler上面的注释里,我们知道,它是直接在CPU的寄存器中读取一些数据,详细格式如下:

//     system call code -- r2
//        arg1 -- r4
//        arg2 -- r5
//        arg3 -- r6
//        arg4 -- r7

当r2值为CS_Exec的话,我们就可以在这个分支里进行进程开启,因此把SyscallException函数设计成一个switch类型的,比较直观:
 

void
ExceptionHandler(ExceptionType which)
{
    int type = machine->ReadRegister(2);

    if (which == SyscallException) {
        swhich(type){
            case SC_Halt:
                   DEBUG('a', "Shutdown, initiated by user program.\n");
                   interrupt->Halt();
                break;
            default: break;
        }
    } else {
    printf("Unexpected user mode exception %d %d\n", which, type);
    ASSERT(FALSE);
    }
}


它本来就实现了SC_Halt,这为我们提供了一个模板,我们写的函数应该都是在syscall.c里面,并且引用syscall.h头文件,这里有接口。

然后,我们可以看到,exec函数只有一个字符串作为参数,返回的是一个spaceID类型。

即便是字符串能用,该如何调用?它应该是一个二进制文件,二进制文件的话,怎么着也得再调用几个函数才行。

在thread中,包含了thread和它的实现,但是仅仅是一个线程类,线程类的话,它并不是进程 ,而我们要造一个进程,除非有一个进程类。然而线程类包含了我们如何工作的,可以先看一看线程类,理解fork是如何工作的。

fork是相当难于理解的,先执行stackallocate函数,它是分配栈的函数,然后凭空出现一个interrupt,这个 应该是一个全局变量,它是中断,它setlevel函数使用,为了关中断,又一个scheduler变量,大概也是一个全局变量 ,它使用readytorun(this),大概就能跑了。这个scheduler在system.h被extern,其实它有一个自己的类,先看看这个scheduler类,它是程序可以运行的关键。

scheduler里面的ReadyToRun里面仅仅是thread的setStatus(Ready),然后在list里面去append,这个大概就是一个管理表的功能,而它的运行,实际上还是在thread类里面。thread里面的setStatus代表可以运行的函数。在run函数里也是这样,只不过它是把前面的那个线程的上下文存储起来了,然后调用新线程的setStatus,

现在还不知道其原理,但是可以预测的是,它在一开始输出什么参数,里面是文件,然后处理一下,把它放到一个公共table表,然后把相应index压入一个寄存器中,再执行中断,那么在中断里就可以获取这个index,进而获取这个文件名,然后开始执行。关键是里面有一个SWITCH(oldThread, nextThread)函数,它的实现是在汇编代码中,好了,现在看thread里面的东西。

但是这个setstatus设计的相当之短,它只有一个status = st,因此说,线程的切换,全在SWITCH里面,既然不会SWITCH,就丢锅给SWITCH。

其实SWITCH也是在这个文件夹里面的,看了一下,它的头文件里面满满的数的定义。在.s文件里面,还真的是二进制文件。。。这里就有一个问题,nachos是在linux里面模拟了一个系统,但是对于CPU的调用还是同一个CPU吧,毕竟汇编代码用到就是CPU里面的东西,它交换数据,还是什么东西,最后一个j,大概就是跳到对应的地址,开始执行。



执行的话,可能是调用machine->Run(这个二进制文件)来实现的,至于文件里是写的什么,暂不做考虑。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值