




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
pintos-pro2-项目2-用户程序Pintosproject2作者:西安电子科技大学王永刚QQ:357543420这个项目将使pintos能够加载并履行用户程序,而且为用户程序供给系统调用。Project2需要达成的的任务有四个:Task1ProcessTerminationMessages进度停止信息Task2ArgumentPassing参数传达Task3SystemCalls系统调用Task4DenyingWritestoExecutables不可以写入可履行文件Task1:ProcessTerminationMessages进度停止信息要求:在进度结束时输出退出代码(就是main函数的返回值,或许异样退出代码。注意:用户进度结束时输入退出代码,核心线程返回时不输入。输出格式被规定以下:printf(“%s:exit(%d)n”,..);实现方法:既然要打印返回值,就得用一个变量保留返回值,于是在structthread构造中加入一个变量回保留返回值:intret;在init_thread( )函数中初始化为0(这里能够不用初始化)。在线程退出里要保留其返回值到ret中,这个将在系统调用里的exit函数中保留,这里先不考虑。在什么地方加入printf( )呢?每个线程结束后,都要调用thread_exit( )函数,假如是加载了用户进度,在thread_exit( )函数中还会调用process_exit( )函数,在process_exit( )函数中,假如是用户进度,那么其页表必定不为NULL,而核心进度页表必定为NULL,即只实用户进度退出时if(pd!=NULL){}就会成立,因此在大括号中加入:printf(“%s:exit(%d)n”,cur->name,cur->ret);此中cur=thread_current( );即目前线程的structthread指针。TASK1OKTASK2ArgumentPassing参数传达要求:分别从命令行传入的文件名和各个参数。依照C函数调用商定,把参数放入栈中。实现方法:1.分别参数的方法:用string.h中的strtok_r( )函数,在string.c中有详尽的说明。在process_execute( )函数中,因为thread_create( )需要一个线程名,此时应当传达给它文件名(不带参数)。可以下办理:char*real_name,*save_ptr;real_name=strtok_r(file_name,"",&save_ptr);tid=thread_create(real_name,PRI_DEFAULT,start_process,fn_copy);(3)在start_process( )函数中,再次分别参数,放入栈中。因为在process_execute( )对file_name作了复制,文件名并未丢掉,但是要注意,不论加载用户程序成功仍是失败,都得开释file_name所占用的一个页的空间(Debughere3weeks)。注意:传给Load( )函数的参数也只好有文件名,因此在load( )函数前要分别出文件名:char*token=NULL,*save_ptr=NULL;token=strtok_r(file_name,"",&save_ptr);success=load(token,&if_.eip,&if_.esp);参数搁置的一种方法:(1)找到用户栈指针:在start_process( )函数中有个构造,此中有一个成员if_.esp,数中为其赋值,分派了栈空间。
structintr_frameif_;这就是用户栈指针,在
这样一load( )函(2)调用strtok_r分别出一个个参数(就是一个个字符串了),把每个字符串都复制到用户栈中,并把他在栈中的地点记录到一个数组中,以备下一步使用。注意:栈是向下增加,而字符串是向上增加。char*esp=(char*)if_.esp;char*arg[256];//assumenumbersofargumentbelow256inti,n=0;for(;token!=NULL;token=strtok_r(NULL,",&save_ptr)){esp-=strlen(token)+1;//becauseuserstackincreasetolowaddr.strlcpy(esp,token,strlen(token)+2);//copyparamtouserstackarg[n++]=esp;}(3)要加入一个双字的对齐,因为是32位的,因此就是四字节对齐。while((int)esp%4make)//wordalignesp--;//注意:栈是向下增加,因此这里是—而不是++;要将第(2)步保留下的指针逆序放入栈中。依照C商定,先要放入一个0,以防没有参数。int*p=esp-4;*p--=0;而后挨次放入参数n的地点,参数n-1的地点参数0的地点。for(i=n-1;i>=0;i--)//placethearguments'pointerstostack*p--=(int*)arg[i];(5)放入argc,argv*p--=p+1;*p--=n;*p--=0;esp=p+1;让用户栈指针指向新的栈顶if_.esp=esp以下列图摆放。假如命令行是:/bin/ls–lfoobar完好代码见附录!TASK3systemcall系统调用要求:(1)实现以下系统调用:pfn[SYS_WRITE]=IWrite;//printf和写文件需要。pfn[SYS_EXIT]=IExit;//退出时return后调用pfn[SYS_CREATE]=ICreate;//创立文件pfn[SYS_OPEN]=IOpen;//翻开文件pfn[SYS_CLOSE]=IClose;//封闭文件pfn[SYS_READ]=IRead;//读文件pfn[SYS_FILESIZE]=IFileSize;//返回文件大小pfn[SYS_EXEC]=IExec;//加载用户程序pfn[SYS_WAIT]=IWait;//等候子进度结束pfn[SYS_SEEK]=ISeek;//挪动文件指针pfn[SYS_REMOVE]=IRemove;//删除文件pfn[SYS_TELL]=ITell;//返回文件指针地点pfn[SYS_HALT]=IHalt;//关机要想达成以上系统调用,还要理解系统调用的体制,见后边。参照文件有:src/lib/user/syscall.c认识每个系统调用的形式。src/lib/syscall-nr.h认识每个系统调用号。实现方法:(1)搭建框架用一个数组保留各函数名,数组下标就是系统调用号。在syscall_init( )函数中初始化数组pfn[]为NULL在syscall_handler( )函数中依照系统调用号调用相函数。typedefvoid(*CALL_PROC)(structintr_frame*);CALL_PROCpfn[MAXCALL];voidsyscall_init(void){intr_register_int(0x30,3,INTR_ON,syscall_handler,"syscall");inti;for(i=0;i<MAXCALL;i++)pfn[i]=NULL;}staticvoidsyscall_handler(structintr_frame*f/*UNUSED*/){if(!is_user_vaddr(f->esp))ExitStatus(-1);intNo=*((int*)(f->esp));if(No>=MAXCALL||MAXCALL<0){printf("Wedon'thavethisSystemCall!\n");ExitStatus(-1);}if(pfn[No]==NULL){printf("thisSystemCall%dnotImplement!\n",No);ExitStatus(-1);}pfn[No](f);}每一个系统调用的实现。完好代码见附录○1SYS_WRITEvoidIWrite(structintr_frame*f)printf函数会调用这个系统调用向屏幕输出,因此不实现这个系统调用,用户程序将无法输出任何字符。写文件也要用这个系统调用。因此要使用pintos自带的一个简单的文件系统。第一从用户栈中拿出三个参数fd,buffer,size假如fd是文件句柄,先要从进度翻开文件表中找到该句柄对应的文件指针再调用pintos供给的file_write( )函数向文件写入数据。翻开文件表将在翻开文件时成立,到SYS_OPEN系统调用实现时再讲其详细实现。假如fd是标准输出stdout句柄则调用putbuf函数向终端输出。○2SYS_EXITvoidIExit(structintr_frame*f);用户程序正常退出会调用这个系统调用。拿出返回值,保留到进度控制块的ret变量中。调用thread_exit( )函数退出进度用户程序非正常退出(如越界接见等原由)需要另加一个函数来实现。voidExitStatus(intstatus)//非正常退出时使用{structthread*cur=thread_current( );cur->ret=status;//保留返回值。thread_exit( );}○3SYS_CREATE创-建文件voidICreate(structintr_frame*f)拿出仅有的一个参数—文件名。调用filesys_create( )函数。保留返回值。○4SYS_OPEN翻开文件voidIOpen(structintr_frame*f)拿出文件名。调用filesys_open( )函数翻开文件。这里需要为每个进度保护一个翻开文件表。翻开文件后要为这个文件分派一个句柄号。在structthread构造中加入:intFileNum;
//
翻开文件数
限制进度翻开文件数structlistfile_list;//intmaxfd;//每翻开一个文件就让maxfd
加
翻开文件列表句柄分派使用1,封闭文件可以不减小。关系文件句柄与文件指针的构造:(被链入file_list)structfile_node{intfd;structlist_elemelem;structfile*f;};有了以上准备,每翻开一个文件都要新创立一个file_node构造,分派句柄,并把file_node加入file_list;最后返回文件句柄就OK.○5SYS_CLOSE—封闭文件voidIClose(structintr_frame*f)一种是封闭一个文件。一种是进度退出时封闭全部文件。从用户栈中获取要封闭文件的句柄。在用户翻开文件列表中找到对应文件,以获取文件指针。调用file_close( )函数封闭文件,开释structfile_node。封闭全部文件自然是每一个都要封闭,开释了。Debughere3weeks○6SYS_READ—读文件IRead( )从用户栈中获取fdbuffersize三个参数假如fd是标准输入设施,则调用input_getc( )假如fd是文件句柄由fd从进度翻开文件表中获取文件指针调用file_read( )函数从文件中读数据。○7SYS_FILESIZE–获取文件大小IFileSize( )从用户栈中获取fd由fd从进度翻开文件表中获取文件指针调用file_length获取文件大小○8SYS_EXEC加载用户程序IExec( )用户程序经过SYS_EXEC这个系统调用创立子进度。在IExec( )函数中,分派一个页,复制一份用户供给的用户名。不然在以后分别参数时,加入’\0’时出现核心线程写入用户内存空间的页错误。还要注意线程同步问题。在IExec( )中调用process_execute( )函数创立子进度,但是从process_execute( )获取了用户进度pid后,用户程序并没用加载。因此要等候用户进度被调动后—调用了start_process( )函数才能知道。Start_process( )函数真实加载用户程序,可能会因为找不到程序言件或内存不足等原由致使加载失败。因此父进度调用process_execute( )后不可以立刻返回,要在一个信号量上等候sema_down(sema),直到start_process( )函数中加载用户程序成功后再semp_up(sema)激活父进度,激活父进度后应当立刻挂起自己—sema_down(sema),这里父进度获取子进度状态信息后,再出父进度sema_up( )激活子进度。假如父进度创立了一个优先级比自己高的子进度,假如不这样坐,start_process( )函数每一次履行sema_up(sema)后,父进度仍是不会被调动,而子进度能够已经运转完成,这样父进度就得不到子进度的状态了。在struct_thread构造中加入semaphoreSemaWaitSuccess;能够在父进度的的这个信号量上等,也但是子进度的SemaWaitSuccess上等。假如子进度创立成功则返回pid,失败返回-1。○9SYS_WAIT—等候函数IWait( )主线程创立子进度后,出于他与子进度优先级同样,因此,两者交替履行,这样主线程就有可能先结束,这致使了一开始的test失败。开初能够经过创立子进度时提升子进度优先级或许在process_wait( )中加入while(true)这样的死循环来解决。后期要经过信号量同步。这个系统调用的需求:父进度创立子进度后可能要等子进度结束。Process_wait( )要返回子进度的返回值。状况有以下:父进度调用process_wait( )时子进度还未结束,此进父进度将被挂起,等子进度结束后再唤醒父进度,父进度再获得返回值。父进度调用process_wait( )时子进度已经结束,这就要求子进度结束后应当把返回值保留到父进度的进度控控制块中。于是在structthread要加入一个链表,structlistsons_ret;构造:structret_data{intpid;intret;structlist_elemelem;};这样就能保留子进度的返回值了。在structthread
构造中加入boolbWait;
表示进度自己有没有被父进度等候。在structthread构造中加入boolSaveData;假如子进度已经把返回值保留到父进度里了就设SaveData为true;SaveData应当被初始化为false;在structthread构造中加入structthread*father;表示父线程。每创立一个子线程,都要在子线程中记录父线程。信号量同步方法:在structthread构造中加入semaphoreSemaWait;这里选择在父进度的SemaWait上等。这个等候会把父进度的structthread进度控制块插入到SemaWait的list中去。要想同时等候多个进度则不行能把父进度插入到多个子进度中去。自然,这里的测试只好等一个子进度,因此在父进度和子进度上等都能够。父进度履行process_wait(child_pid)进度structthread指针t。经过遍历
后,能够由all_list
child_pid比较pid
获取子实现.假如在all_list没有发现子进度的进度控制块或许发现t->SaveData==true||t->status==THREAD_DYING;表示子进度已经结束,直接从自己的sons_ret链表中找到子进度的返回值返回就OK.假如子进度还在运转,则履行sema_down(t->father->SemaWait)把自己挂起,子进度履行完成后,发此刻bWait==true,自己被等候了,再开释父进度sema_up(SemaWait);假如bWait==fale,则不用唤醒父进度。父进度被唤醒后,再从sons_ret链表中获取子进度的返回值。每个子进度只好等一次,第二次等同一个子进度只好返回-1.一个进度结束时,在process_exit( )函数中,要开释自己翻开的全部文件,保留返回值到父进度,输出退出信息,假如有父进度在等他就唤醒父进度,开释子进度链表。○10SYS_SEEK挪动文件指针ISeek( )从用户栈中拿出文件句fd柄要挪动的距离,把fd转为文件指针,调用file_seek( )函数挪动文件指针即可。○11SYS_REMOVE删除文件IRemove从用户栈中拿出要删除文件的文件名。调用filesys_remove( )删除文件。○12SYS_TELL返回文件指针目前地点ITell( )从用户栈中拿出文件句fd柄要挪动的距离,把fd转为文件指针,调用file_tell( )函数获取指针地点。○13SYS_HALT关机IHALT调用shutdown_power_off( )函数关机用户程序致使页错误时,会进入page_fault( )函数,在exception.c中。在page_fault( )中加入if(not_present||(is_kernel_vaddr(fault_addr)&&user))ExitStatus(-1);来办理页错误。Task4DenyingWritestoExecutables不可以写入可履行文件在start_process函数中加入t->FileSelf=filesys_open(token);file_deny_write(t->FileSelf);此中FileSelf
变量是要在
structthread
结构中增添的。进度退出时就排除:在process_exit( )中加入if(cur->FileSelf!=NULL)//己人deny_write
撤除对自{file_allow_write(cur->FileSelf);file_close(cur->FileSelf);}注意:全部系统调用的返回值都放到用户的eax寄存器中。拿出参数时要对用户栈指针作详尽的检查,能否越界,越界则直接调用Exit_Status(-1)中断用户进度。用户程序加载过程:(1)核心线程经过调用process_execute(char*file_name);函数来创立用户进度。File_name为要加载的文件名。这个函数中还调用了thread_create( )函数为用户进度创立了一个线程。File_name和一个叫start_process的函数被传达给了thread_create( ),thread_create( )函数创立线程后就把线程放入ready_list( )等候被调动;(2)获取CPU后就开始start_process(void*file_name)函数。这个函数做了以下几件事儿:○1依据file_name把用户程序从硬盘调入内存,还为其分派了虚构内存。注意这里要达成task2,不然文件名不正确,就无法翻开文件。○2给用户分派了栈空间3GB开始。向低字节增加。在这里要实现参数分别,而且把参数按规定放入用户栈中。(3)经过内嵌汇编asmvolatile(.)调用了用户程序中的main( )函数。(4)main( )函数从栈中拿出传给他的参数,履行完成后会调用系统调用exit( ),Exit( )函数又调用thread_exit( )函数,thread_exit( )函数又调用process_exit( )函数,最后在thread_exit()函数中把马上退出的函数的进度控制块structthread从all_list中remove掉,调用了进度调动器schedule( )函数,调用下一下进度履行。系统调用过程:在用户程序使用一个系统调用,如printf( );在必定会触发一个30号中断,正如src/lib/user/syscall.c文件中所述。可见参数个数不一样,系统调用不一样。这个30号中断调用以前,把系统调用号、用户参数(0到3个不等)压入栈中。而后开始履行中断程序,中断程序又调用了syscall_handler(structintr_frame*f)函数,此中f是一个指向了用户程序目前运转信息的的指针,此中就实用户栈指针esp,因此在我们增添的系统调用中,就能够依据这个指针拿出系统调用号和各个参数。系统调用结束后,要把返回值入如f->eax中.注意:用户栈中的各个参数其实不连续寄存:三个参数write(fd,buffer,size);intfd=*(esp+2);char*buffer=(char*)*(esp+6);unsignedsize=*(esp+3);两个参数create(pFileName,size);boolret=filesys_create((constchar*)*((unsignedint*)f->esp+4),*((unsignedint*)f->esp+5));一个参数exit(-1);cur->ret=*((int*)f->esp+1);附录:Task2参数传达代码(红色)Task3系统调用(蓝色)Task4denywrite(绿色)tid_tprocess_execute(constchar*file_name){char*fn_copy;tid_ttid;/*MakeacopyofFILE_NAME.Otherwisethere'saracebetweenthecallerandload( ).*/fn_copy=palloc_get_page(0);if(fn_copy==NULL)returnTID_ERROR;strlcpy(fn_copy,file_name,PGSIZE);char*real_name,*save_ptr;real_name=strtok_r(file_name,"",&save_ptr);/*CreateanewthreadtoexecuteFILE_NAME.*/tid=thread_create(real_name,PRI_DEFAULT,start_process,fn_copy);if(tid==TID_ERROR)palloc_free_page(fn_copy);returntid;}/*Athreadfunctionthatloadsauserprocessandstartsitrunning.*/staticvoidstart_process(void*file_name_){char*file_name=file_name_;structintr_frameif_;boolsuccess;char*token=NULL,*save_ptr=NULL;token=strtok_r(file_name,"",&save_ptr);//getrealfilename,useitinload( )/*Initializeinterruptframeandloadexecutable.*/memset(&if_,0,sizeofif_);if_.gs=if_.fs=if_.es=if_.ds=if_.ss=SEL_UDSEG;if_.cs=SEL_UCSEG;if_.eflags=FLAG_IF|FLAG_MBS;success=load(token,&if_.eip,&if_.esp);structthread*t=thread_current( );if(!success){palloc_free_page(file_name);t->tid=-1;sema_up(&t->SemaWaitSuccess);ExitStatus(-1);}sema_up(&t->SemaWaitSuccess);t->FileSelf=filesys_open(token);file_deny_write(t->FileSelf);char*esp=(char*)if_.esp;char*arg[256];//assumenumbersofargumentbelow256inti,n=0;for(;token!=NULL;token=strtok_r(NULL,"",&save_ptr))//copytheargumenttouserstack{esp-=strlen(token)+1;//becauseuserstackincreasetolowaddr.strlcpy(esp,token,strlen(token)+2);//copyparamtouserstackarg[n++]=esp;}while((int)esp%4make)//wordalignesp--;int*p=esp-4;*p--=0;//first0for(i=n-1;i>=0;i--)//placethearguments'pointerstostack*p--=(int*)arg[i];*p--=p+1;*p--=n;*p--=0;esp=p+1;if_.esp=esp;newstacktop
//setpalloc_free_page(file_name);asmvolatile("movl%0,%%esp;jmpintr_exit"::"g"(&if_):"memory");NOT_REACHED( );}Syscall.c中全部代码:#include"userprog/syscall.h"#include"threads/vaddr.h"#include<stdio.h>#include<syscall-nr.h>#include"threads/interrupt.h"#include"threads/thread.h"#include"filesys/filesys.h"#include"filesys/file.h"#include"devices/input.h"#include"process.h"#include<string.h>#include"devices/shutdown.h"#defineMAXCALL21#defineMaxFiles200#definestdin1staticvoidsyscall_handler(structintr_frame*);typedefvoid(*CALL_PROC)(structintr_frame*);CALL_PROCpfn[MAXCALL];voidIWrite(structintr_frame*);voidIExit(structintr_frame*f);voidExitStatus(intstatus);voidICreate(structintr_frame*f);voidIOpen(structintr_frame*f);voidIClose(structintr_frame*f);voidIRead(structintr_frame*f);voidIFileSize(structintr_frame*f);voidIExec(structintr_frame*f);voidIWait(structintr_frame*f);voidISeek(structintr_frame*f);voidIRemove(structintr_frame*f);voidITell(structintr_frame*f);voidIHalt(structintr_frame*f);structfile_node*GetFile(structthread*t,intfd);voidsyscall_init(void){intr_register_int(0x30,3,INTR_ON,syscall_handler,"syscall");inti;for(i=0;i<MAXCALL;i++)pfn[i]=NULL;pfn[SYS_WRITE]=IWrite;pfn[SYS_EXIT]=IExit;pfn[SYS_CREATE]=ICreate;pfn[SYS_OPEN]=IOpen;pfn[SYS_CLOSE]=IClose;pfn[SYS_READ]=IRead;pfn[SYS_FILESIZE]=IFileSize;pfn[SYS_EXEC]=IExec;pfn[SYS_WAIT]=IWait;pfn[SYS_SEEK]=ISeek;pfn[SYS_REMOVE]=IRemove;pfn[SYS_TELL]=ITell;pfn[SYS_HALT]=IHalt;}staticvoidsyscall_handler(structintr_frame*f/*UNUSED*/){if(!is_user_vaddr(f->esp))ExitStatus(-1);intNo=*((int*)(f->esp));if(No>=MAXCALL||MAXCALL<0){printf("Wedon'thavethisSystemCall!\n");ExitStatus(-1);}if(pfn[No]==NULL){printf("thisSystemCall%dnotImplement!\n",No);ExitStatus(-1);}pfn[No](f);}voidIWrite(structintr_frame*f)//三个参数{int*esp=(int*)f->esp;if(!is_user_vaddr(esp+7))ExitStatus(-1);intfd=*(esp+2);//
文件句柄char*buffer=(char*)*(esp+6);//
要输出人缓冲unsignedsize=*(esp+3);//输出内容大小。if(fd==STDOUT_FILENO)//标准输出设施{putbuf(buffer,size);f->eax=0;}else
//
文件{structthread*cur=thread_current( );struct
file_node*fn=GetFile(cur,fd);//
获取文件指针if(fn==NULL){f->eax=0;return;}f->eax=file_write(fn->f,buffer,size);//写文件}}voidIExit(structintr_frame*f)//一个参数正常退出时使用{if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);structthread*cur=thread_current( );cur->ret=*((int*)f->esp+1);f->eax=0;thread_exit( );}voidExitStatus(intstatus)//非正常退出时使用{structthread*cur=thread_current( );cur->ret=status;thread_exit( );}voidICreate(structintr_frame*f)//两个参数{if(!is_user_vaddr(((int*)f->esp)+6))ExitStatus(-1);if((constchar*)*((unsignedint*)f->esp+4)==NULL){f->eax=-1;ExitStatus(-1);}boolret=filesys_create((constchar*)*((unsignedint*)f->esp+4),*((unsignedint*)f->esp+5));f->eax=ret;}voidIOpen(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);structthread*cur=thread_current( );constchar*FileName=(char*)*((int*)f->esp+1);if(FileName==NULL){f->eax=-1;ExitStatus(-1);}structfile_node*fn=(structfile_node*)malloc(sizeof(structfile_node));fn->f=filesys_open(FileName);if(fn->f==NULL||cur->FileNum>=MaxFiles)//fn->fd=-1;elsefn->fd=++cur->maxfd;f->eax=fn->fd;if(fn->fd==-1)free(fn);else{cur->FileNum++;list_push_back(&cur->file_list,&fn->elem);}}voidIClose(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);structthread*cur=thread_current( );intfd=*((int*)f->esp+1);f->eax=CloseFile(cur,fd,false);}intCloseFile(structthread*t,intfd,intbAll){structlist_elem*e,*p;if(bAll){while(!list_empty(&t->file_list)){structfile_node*fn=list_entry(list_pop_front(&t->file_list),structfile_node,elem);file_close(fn->f);free(fn);}t->FileNum=0;return0;}for(e=list_begine!=list_end(&t->file_list);)
(&t->file_list);{structfile_node*fn=list_entry(e,structfile_node,elem);if(fn->fd==fd){list_remove(e);if(fd==t->maxfd)t->maxfd--;t->FileNum--;file_close(fn->f);free(fn);return0;}}}voidIRead(structintr_frame*f){int*esp=(int*)f->esp;if(!is_user_vaddr(esp+7))ExitStatus(-1);intfd=*(esp+2);char*buffer=(char*)*(esp+6);unsignedsize=*(esp+3);if(buffer==NULL||!is_user_vaddr(buffer+size)){f->eax=-1;ExitStatus(-1);}structthread*cur=thread_current( );structfile_node*fn=NULL;unsignedinti;if(fd==STDIN_FILENO)从标准输入设施读{for(i=0;i<size;i++)buffer[i]=input_getc( );}else//从文件读{fn=GetFile(cur,fd);//获取文件指针if(fn==NULL){f->eax=-1;return;}f->eax=file_read(fn->f,buffer,size);}}structfile_node*GetFile(structthread*t,intfd)依照文件句柄从进度翻开文件表中找到文件指针{structlist_elem*e;for(e=list_begin(&t->file_list);e!=list_end(&t->file_list);e=list_next(e)){structfile_node*fn=list_entry(e,structfile_node,elem);if(fn->fd==fd)returnfn;}returnNULL;}voidIFileSize(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);structthread*cur=thread_current( );intfd=*((int*)f->esp+1);structfile_node*fn=GetFile(cur,fd);if(fn==NULL){f->eax=-1;return;}f->eax=file_length(fn->f);}voidIExec(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);constchar*file=(char*)*((int*)f->esp+1);tid_ttid=-1;if(file==NULL){f->eax=-1;return;}char*newfile=(char*)malloc(sizeof(char)*(strlen(file)+1));memcpy(newfile,file,strlen(file)+1);tid=process_execute(newfile);structthread*t=GetThreadFromTid(tid);sema_down(&t->SemaWaitSuccess);f->eax=t->tid;t->father->sons++;free(newfile);sema_up(&t->SemaWaitSuccess);}voidIWait(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);tid_ttid=*((int*)f->esp+1);if(tid!=-1){f->eax=process_wait(tid);}elsef->eax=-1;}voidISeek(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+6))ExitStatus(-1);intfd=*((int*)f->esp+4);unsignedintpos=*((unsignedint*)f->esp+5);structfile_node*fl=GetFile(thread_current( ),fd);file_seek(fl->f,pos);}voidIRemove(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);char*fl=(char*)*((int*)f->esp+1);f->eax=filesys_remove(fl);}voidITell(structintr_frame*f){if(!is_user_vaddr(((int*)f->esp)+2))ExitStatus(-1);intfd=*((int*)f->esp+1);structfile_node*fl=GetFile(thread_current( ),fd);if(fl==NULL||fl->f==NULL){f->eax=-1;return;}f->eax=file_tell(fl->f);}voidIHalt(structintr_frame*f){shutdown_power_off( );f->eax=0;}intprocess_wait(tid_tchild_tid){structthread*t=GetThreadFromTid(child_tid);if(t==NULL||t->status==THREAD_DYINGt->SaveData)//子进度已经把返回值保留到Sons_ret链表中了{intret=-1;ret=GetRetFromSonsList(thread_current( ),child_tid);//从sons_ret中取回子进度的返回值returnret;}t->bWait=true;sema_down(&t->father->SemaWait);在这个信号量上等。intret=-1;ret=GetRetFromSonsList(thread_current( ),child_tid);returnret;}intGetRetFromSonsList(structthread*t,tid_ttid){structlist_elem*e;intret=-1;for(e=list_begin(&t->sons_ret);e!=list_end(&t->sons_ret);e=list_next(e)){structret_data*rd=list_entry(e,structret_data,elem);if(rd->tid==tid){ret=rd->ret;rd->ret=-1;
//
每个子进度只好被等一次
,第二此等返回
-1break;}}returnret;}/*Freethecurrentprocess'sresources.*/voidprocess_exit(void){structthread*cur=thread_current( );uint32_t*pd;/*Destroythecurrentprocess'spagedirectoryandswitchbacktothekernel-onlypagedirectory.*/pd=cur->pagedir;if(pd!=NULL){/*
Correct
ordering
hereis
crucial.Wemustsetcur->pagedir
to
NULL
beforeswitchingpagedirectories,sothatatimerinterruptcan'tswitchbacktotheprocesspagedirectory.Wemustactivatethebasepagedirectorybeforedestroyingtheprocess'spagedirectory,orouractivepagedirectorywillbeonethat'sbeenfreed(andcleared).*/CloseF
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 淡水彩古典花纹毕业答辩设计
- 礼仪教育之德育主题班会
- CPA税法基础知识课件
- BIM基础知识课件
- 吉林职业技术学院《生物化学与分子生物化学A》2023-2024学年第二学期期末试卷
- 曲靖市富源县2024-2025学年三年级数学第二学期期末复习检测模拟试题含解析
- 2025年湖南长郡教育集团重点中学初三一模化学试题试卷含解析
- 辽宁铁道职业技术学院《现代交换原理》2023-2024学年第二学期期末试卷
- 天津理工大学中环信息学院《专业综合技能培训》2023-2024学年第二学期期末试卷
- 湖南交通工程学院《设计与市场》2023-2024学年第一学期期末试卷
- 2024-2025年人教版七下语文期中复习-专题01 基础知识积累(考点串讲)
- 2025重庆西南证券股份有限公司招聘45人笔试参考题库附带答案详解
- 湖南省示范性高中2024-2025学年高二下学期2月联考 物理试卷(含解析)
- 2025年《宏观经济政策与发展规划》考前通关必练题库(含答案)
- 服装公司品质(质量)管理手册
- 一年级道德与法治下册素养教案第10课 相亲相爱一家人
- 办公楼弱电系统设计方案
- 私募投资学试题及答案
- 2025年合肥二模数学试题及答案
- 不要慌太阳下山有月光二部合唱简谱
- 干净整洁的个人卫生习惯
评论
0/150
提交评论