讨论:Nachos 2013: Multiprogramming
要怎么知道一个process是否是正常退出的?
A1:The exit status of a process that exits abnormally is up to you.
A2:exit什么值都是正常的,理论上不应该依赖于对于status的值判断是否正常退出。不正常推出主要是指exception或者unknown systemcall。
A3:Nachos就是一个低幼的操作系统。如果真的有什么操作系统不认识的情况出现,操作系统就会崩掉,而不仅仅是进程非正常结束。所以不正常结束,可以视为操作系统知道发生的是什么,但不知道怎么处理。
具体来说,就是操作系统发现出现问题后,他的所有处理方案都不能用,就只能不正常结束了。
A4:“The exit status of the exiting process should be transferred to the parent, in case the parent calls the join system call. The exit status of a process that exits abnormally is up to you. For the purposes of join, a child process exits normally if it calls the exit syscall with any status, and abnormally if the kernel kills it (e.g. due to an unhandled exception).”
举个例子:如果进程还能继续跑,就没有什么能说明它是否在正常跑,也就没有干掉它的理由。只有当进程发现,它无法继续跑了,它就会给操作系统抛个异常。操作系统看到这个异常,就去处理这个异常。如果是操作系统认识的异常,比如open,操作系统就会去做,然后再给进程去做。但如果操作系统不知道怎么处理这个异常,它就有干掉这个进程的理由。这个时候,它才会干掉这个进程。于是干掉子线程并且让父线程知道,就是操作系统需要做的事情。
作为一个进程,他抛异常是因为他做不下去了,让操作系统帮他继续做下去。于是它是不应该知道操作系统能处理哪些问题,不能处理哪些问题的。至于怎么搞死它,只要能让父进程知道你把他儿子搞死了,怎么做都可以。
跑test_exit,test_matmult的时候会出现exceptionReadOnly和exceptionIllegalInstruction
A:For the purposes of join, a child process exits normally if it calls the exit syscall with any status, and abnormally if the kernel kills it (e.g. due to an unhandled exception).
stdin stdout要上锁吗?
A1:Do not implement any kind of file locking; this is the file system's responsibility.
A2:看UserKernel.console.openForReading()的实现。另外Nachos的每个进程都只有一个线程。
lotteryScheduler里pickNextThread的时候是自己随机一个数,然后随便选个priority比这个数大的thread吗?
A:[n1,n2,n3,n4,n5]
假设上面是一个队列中各个线程持有的彩票的数量,一种实现方法是产生一个1-(n1+n2+n3+n4+n5)之间的随机数,然后这个随机数落到哪个区间就选择哪个线程。
测试的话,比如一个线程还在等待锁,你让它运行了,当然是不可以的,但是一个有两张彩票,一个有3张彩票,哪个到底下一个运行,我们是没法测的。但是后面的phase3中,你的lotteryScheduler如果有问题,很可能会超时。
操作系统自身的内存使用是由谁管里的?
Q:操作系统本身有很多数据结构,队列啊什么。我们好像想建一个队列就建一个,而它们好像是游离在整个内存区域之外的。但是操作系统的这些数据结构的存储也应该是在内存里啊。那它们是由谁怎么管理的?
A:Nachos是运行在jvm上的,不是运行在硬件之上的,和真实的操作系统有区别。
Phase 2该如何运行?
Q:Phase 2该如何运行啊?我无论设置什么coff,比如-[] nachos-sjtu/conf/proj2.conf -- nachos.ag.CoffGrader -x hello.coff,结果都是
Testing the console device. Typed characters
will be echoed until q is typed.
然后就卡住了,输了q也没什么用。求问这是什么情况?
A:把UserKernel.selfTest()的内容注释掉。
test_files3
如果有人跟我一样苦逼地在调test_files3的话。。。友情提示一下,如果运行完了,如果一个苦逼的on_the_fly_delete还存在在test文件夹里的话,要苦逼地将它手动删掉。。。
反正我是在它把自己删掉之前程序就跪了,没等到它把自己删掉。。导致后来再跑都提前跪了。。。T.T
对于test_file的一点声明
linux 和 windows不同的区别让我们注意到:
A stub file system interface to the UNIX file system is already provided for you
所以实际情况应该是:
对于大部分操作win和linux是一致的,但对于unlink这个操作两边不一致。
很多涉及unlink的问题,在linux下很可能就是完全正确的,但在win下评测,被评测为错误。
在handleExit里加一句 coff.close();
没过test_file2的同学在handleExit里加一句 coff.close();
grader_user1.coff的运行参数是什么?
A:用到的是: -[] conf/proj2.conf -- nachos.ag.UserGrader1 -x grader_user1.coff
所有测试用的都是pre里APhase2的内容。
关于shCXR.coff
Q:它是新建了几个process跑,没有用join,然后主程序exit了。 这时候是应该等那几个在后台跑的process跑完还是主程序跑完就halt?
A:最后一个process结束的时候负责关机
怎么把输出里面一大堆汇编去掉?
A:把参数里的-d ma去掉就行了
File名字最长是多少?
Q:那些filename 是 char *,我想用readVirtualMemoryString读出来,那设置的maxLength应该是多少?
A:'User processes store filenames and other string arguments as null-terminated strings in their virtual address space. The maximum length of for strings passed as arguments to system calls is 256 bytes. '
印象中从来没有考虑过文件名大于256的情况。。。
phyPageNum大小需要多少?
A:对于不同的测试点,会有不同的Configure需求,每个Phase都是这样。
在phase2里,至少要开到256才能保证样例数据。
一个文件可以多次open?
A:以下结论仅供你们参考
1. creat返回的fd是可读写的,不必要再open一次;
2. 但是creat之后再open也是允许的。换句话说,一个文件允许被open多次;
3. 既然允许被open多次,就允许被close多次,比如下面的代码合法:
int fd1, fd2;
fd1 = create("test");
fd2 = open("test");
close(fd1);
close(fd2);
这里的fd1和fd2是否相同,取决于你们实现。我当时是返回不同的fd;
4. 允许多个进程对同一个文件读写。这在主流操作系统也是允许的(主流操作系统在open的时候大多可以指定是否与其他进程共享这个文件;但是nachos比较简陋,可以认为永远允许)。但是同时读写产生的结果是未定义的;
5. 上面这条的意思是说同时读写同一个文件,read和write可以返回以任意顺序进行读写的返回值,但是不可以造成对文件系统的破坏。这是要在文件系统里做的。
exit和join的调用顺序,以及传递status的机制
Q:刚才看了\test\syscall.h,有一个问题求问助教:
关于void exit(int status)和int join(int pid, int *status)
这里面两句话看得我一头雾水:
在exit的注释里有句话:
status is returned to the parent process as this process's exit status and can be collected using the join syscall.
在join的注释里有句话:
status points to an integer where the exit status of the child process will be stored. This is the value the child passed to exit().
本来对join还是比较清楚的,看完这段就什么都不懂了。。。助教能否解释一下exit和join的调用顺序,以及传递status的机制?
A:当调用join的时候,父线程停止运行,子线程运行,子线程运行完了,父线程当然是从join处接着运行,join的地方发生了线程的切换,status可以设置一个父线程子线程都认识的地方存就行了。
请问怎么给测试程序加参数?
Q:比如echo.c中argc和argv是如何提供的?
A:注意在UserKernel中Run()过程Lib.assertTrue(process.execute(shellProgram, new String[] { }));
这里可以传递参数,但从外部Nachos直接传参数是不行的
评测时直接在c中将参数写入后编译成coff,保证测试数据中不含参数,也不会改动你们的程序
handleExec(....)打开的可执行文件,要不要用一个descriptor记录下来?
A:不要,这不是打开文件,这是load程序代码
如果一个文件被同一个进程open了两次,那么第二次open应该返回什么?
Q:1. 如果一个文件被同一个进程open了两次,那么第二次open应该返回什么?-1?旧的描述符?还是新的描述符?这里假设两次打开都成功;
2. 要是把上面问题中的任何一个或者两个open替换成creat,结果也是一样的吗?
A:1.在phase2不需要关心这个问题,因为你是直接调用filesystem,filesystem返回什么你就把它返回给用户。不必检查是否文件已经打开过。
2.同上
总结一下测试几个coff的方法
1. 确保你的framework是最新的( 其实是因为AutoGrader升级了 )
2. 建立test文件夹,使得其与你的工程nachos-sjtu在同一级文件夹(即保持svn的目录结构,如果本来就用svn目录结构的同学就不用管了)
不想使用原有test路径的同学,需要在conf里添加FileSystem.testDirectory,同时运行时要在 -#后添加参数testRoot。
注意: 如果不这样做的话你不仅要设定FileSystem.testDirectory还要改CoffGrader的路径处理,否则找不到*.out
3. 将test-case-preview/phase2/testcases中的所有文件不带目录地copy到那个test文件夹里,同时确保nachos-framework/test里的文件(*.c啊*.coff啊什么的)也都在test文件夹里
4. 测试: -- nachos.ag.CoffGrader -[] YOUR_CONFIGURE_FILE_PATH -x TEST_GRADER [ -# output=STANDARD_ANSWER_FILE ]
Example: -- nachos.ag.CoffGrader -[] conf/proj2.conf -x test_matmult.coff -# output=test_matmult.out
注意: --后面有空格!!!output是指标准答案文件,用来比较的,不是用来输出到文件的。。。
Reference:
[1]. XiaoJia - 关于运行phase2的preview testcases的一点心得(?)。。。
preview的testcase里,sample.sh里是不是拼写错误了
Q:
matmult echo 123 matmult & matmult & matmult & matmult & matmult & exut exit end
倒数第三行和倒数第二行差距比较大啊,是故意而为之?
A:这个是故意的。正确情况就应该是exec failed。
exut.coff这个文件是不存在的,所以不能执行,所以你的nachos需要容忍这种情况,但又不影响其他程序。
用户的进程认为他虚地址空间是无限大的吗?
A:不是无限大,是足够大。在这里就是物理内存的大小,phase3就是虚拟内存的大小
如果一个新创建的进程所需要的页表数当前的物理内存不能满足,那么要不要执行换页操作?
A:不需要,phase3的内容,这里只需要假设内存够大就行了
一个UserKernel在一次simulate中只会有一个吗?
A:对
如果父进程exit了,那么要让所有的子进程exit吗?
A:spec目前没有要求,那就应该不会有这样的数据
PS:你们可以多看看Processor里面的函数,有些比较有用的,比如pageFromAddress等。
hint: 在UserProcess.loadSections()里面有一行注释,// for now, just assume virtual addresses=physical addresses,这里是要初始化pageTable的。
hint2: 注意在分配内存的时候的同步性问题。
创建文件的时候用不用考虑文件名重名的问题?
A:在phase2你只需要调用filesystem,你不用实现filesystem,所以不需要care这个,因为你并不实现创建文件的逻辑
每个进程包含一个还是多个线程?
A:在nachos里是单线程
standard input and standard output被关闭后,0和1两个文件描述符其他文件还能用吗?
A:应该是不能用的吧。。。不过没有这么bt的数据吧
能不能解释一下coff是怎么回事?
A:coff就理解成exe吧,或者是汇编代码,ld a(b), r1; add r1 r2 r3之类的,Processor会解释他们并进行计算。
create一个文件后要不要在进程中保留下来?也就是要不要给它个文件标识符?
Q:看Nachos代码中的comment似乎是要返回文件标识符的
不过在cp.c中
creat(argv[2]); dst = open(argv[2]); ...... close(dst);
如果create要在进程中保存文件对象的话,那么程序中并没有close这个文件对象将会导致这个文件不能被删除
所以我个人感觉不需要为create在进程中保存下文件对象,不知是不是这样?
A:syscall的语义请严格按照syscall.h中的specification实现
"Returns the new file descriptor, or -1 if an error occurred."
用户程序如何写不能作为参考标准,但有一点:只要程序合法,你不能让他crash
比如你说的cp.c先creat再open,这个没有问题,哪怕open很多此也没有问题,一直不close也没有问题,因为OS要负责在进程退出时回收所有资源(file descriptor table, file table entry等)
我们只能表示这样的程序写的不好,会在退出之前占用不必要的资源(遗憾的是事实上这种程序遍地都是……)