




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Pintos project2作者:西安電子科技大學(xué)王永剛 QQ:357543420這個(gè)項(xiàng)目將使pintos可以加載并執(zhí)行用戶程序,并且為用戶程序提供系統(tǒng)調(diào)用。Project2 需要完成的的任務(wù)有四個(gè): Task1 Process Termination Messages進(jìn)程終止信息 Task2 Argument Passing 參數(shù)傳遞 Task3 System Calls 系統(tǒng)調(diào)用 Task4 Denying Writes to Executables不能寫入可執(zhí)行文件Task1: Process Termination Messages進(jìn)程終止信息要求: 1.在進(jìn)程結(jié)束時(shí)輸出退出代碼(就
2、是main函數(shù)的返回值,或者異常退出代碼。 注意: 用戶進(jìn)程結(jié)束時(shí)輸入退出代碼,核心線程返回時(shí)不輸入。輸出格式被規(guī)定如下: printf (“%s: exit(%d)n”,.); 實(shí)現(xiàn)方法:1. 既然要打印返回值,就得用一個(gè)變量保存返回值,于是在struct thread 結(jié)構(gòu)中加入一個(gè)變量回保存返回值:int ret; 在init_thread()函數(shù)中初始化為0(這里可以不用初始化)。2. 在線程退出里要保存其返回值到ret中,這個(gè)將在系統(tǒng)調(diào)用里的exit函數(shù)中保存,這里先不考慮。在什么地方加入printf()呢?每個(gè)線程結(jié)束后,都要調(diào)用thread_exit()函數(shù),如果是加載了用戶進(jìn)程
3、,在thread_exit()函數(shù)中還會(huì)調(diào)用process_exit()函數(shù), 在process_exit()函數(shù)中,如果是用戶進(jìn)程,那么其頁表一定不為NULL,而核心進(jìn)程頁表一定為NULL,即只有用戶進(jìn)程退出時(shí)if(pd!=NULL) 就會(huì)成立,所以在大括號(hào)中加入:printf (“%s: exit(%d)n”,cur-name,cur-ret);其中cur=thread_current();即當(dāng)前線程的struct thread 指針。TASK1 OKTASK2 Argument Passing 參數(shù)傳遞要求:1. 分離從命令行傳入的文件名和各個(gè)參數(shù)。2. 按照C函數(shù)調(diào)用約定,把參數(shù)放入棧
4、中。實(shí)現(xiàn)方法:1.分離參數(shù)的方法:用string.h中的strtok_r()函數(shù),在string.c中有詳細(xì)的說明。2.在process_execute()函數(shù)中,因?yàn)閠hread_create()需要一個(gè)線程名,此時(shí)應(yīng)該傳遞給它文件名(不帶參數(shù))??扇缦绿幚恚篶har *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()函數(shù)中,再次
5、分離參數(shù),放入棧中。由于在process_execute()對(duì)file_name作了復(fù)制,文件名并未丟失,但是要注意,無論加載用戶程序成功還是失敗,都得釋放file_name所占用的一個(gè)頁的空間(Debug here 3 weeks)。 注意:傳給Load()函數(shù)的參數(shù)也只能有文件名,所以在load()函數(shù)前要分離出文件名:char *token=NULL, *save_ptr=NULL;token = strtok_r (file_name, , &save_ptr);success = load (token, &if_.eip, &if_.esp);參數(shù)放置的一種方法:(1)找到用戶棧指
6、針:在start_process()函數(shù)中有struct intr_frame if_; 這樣一個(gè)結(jié)構(gòu),其中有一個(gè)成員if_.esp,這就是用戶棧指針,在load()函數(shù)中為其賦值,分配了棧空間。(2)調(diào)用strtok_r 分離出一個(gè)個(gè)參數(shù)(就是一個(gè)個(gè)字符串了),把每個(gè)字符串都復(fù)制到用戶棧中,并把他在棧中的位置記錄到一個(gè)數(shù)組中,以備下一步使用。注意:棧是向下增長,而字符串是向上增長。 char *esp=(char *)if_.esp; char *arg256; /assume numbers of argument below 256 int i,n=0; for (; token !=
7、NULL;token = strtok_r (NULL, , &save_ptr) esp-=strlen(token)+1; /because user stack increase to low addr. strlcpy(esp,token,strlen(token)+2); /copy param to user stack argn+=esp; (3)要加入一個(gè)雙字的對(duì)齊,因?yàn)槭?2位的,所以就是四字節(jié)對(duì)齊。while(int)esp%4make) /word align esp-; /注意:棧是向下增長,所以這里是而不是+;(4)要將第(2)步保存下的指針逆序放入棧中。按照C約定,
8、先要放入一個(gè)0,以防沒有參數(shù)。 int *p=esp-4; *p-=0; 然后依次放入?yún)?shù)n的地址,參數(shù)n-1的地址 參數(shù)0的地址。for(i=n-1;i=0;i-) /place the arguments pointers to stack *p-=(int *)argi;(5)放入argc,argv*p-=p+1; *p-=n; *p-=0; esp=p+1;(6)讓用戶棧指針指向新的棧頂 if_.esp=esp如下圖擺放。 如果命令行是:/bin/ls l foo bar完整代碼見附錄!TASK 3 system call 系統(tǒng)調(diào)用要求:(1)實(shí)現(xiàn)以下系統(tǒng)調(diào)用: pfnSYS_WRIT
9、E=IWrite; /printf和寫文件需要。 pfnSYS_EXIT=IExit; /退出時(shí)return后調(diào)用 pfnSYS_CREATE=ICreate; /創(chuàng)建文件 pfnSYS_OPEN=IOpen;/打開文件 pfnSYS_CLOSE=IClose; /關(guān)閉文件 pfnSYS_READ=IRead; / 讀文件 pfnSYS_FILESIZE=IFileSize; /返回文件大小 pfnSYS_EXEC=IExec; /加載用戶程序 pfnSYS_WAIT=IWait;/等待子進(jìn)程結(jié)束 pfnSYS_SEEK=ISeek; /移動(dòng)文件指針 pfnSYS_REMOVE=IRemove
10、; /刪除文件 pfnSYS_TELL=ITell; /返回文件指針位置 pfnSYS_HALT=IHalt; /關(guān)機(jī)要想完成以上系統(tǒng)調(diào)用,還要明白系統(tǒng)調(diào)用的機(jī)制,見后邊。參考文件有:src/lib/user/syscall.c 了解每個(gè)系統(tǒng)調(diào)用的形式。 src/lib/syscall-nr.h 了解每個(gè)系統(tǒng)調(diào)用號(hào)。實(shí)現(xiàn)方法:(1) 搭建框架用一個(gè)數(shù)組保存各函數(shù)名,數(shù)組下標(biāo)就是系統(tǒng)調(diào)用號(hào)。在syscall_init()函數(shù)中初始化數(shù)組pfn為NULL在syscall_handler()函數(shù)中依據(jù)系統(tǒng)調(diào)用號(hào)調(diào)用相函數(shù)。typedef void (*CALL_PROC)(struct intr_f
11、rame*);CALL_PROC pfnMAXCALL;voidsyscall_init (void) intr_register_int (0x30, 3, INTR_ON, syscall_handler, syscall); int i; for(i=0;iesp) ExitStatus(-1); int No=*(int *)(f-esp); if(No=MAXCALL|MAXCALLret=status; /保存返回值。 thread_exit();SYS_CREATE-創(chuàng)建文件 void ICreate(struct intr_frame *f) 取出僅有的一個(gè)參數(shù)文件名。調(diào)用fi
12、lesys_create()函數(shù)。保存返回值。SYS_OPEN-打開文件void IOpen(struct intr_frame *f)取出文件名。調(diào)用filesys_open()函數(shù)打開文件。這里需要為每個(gè)進(jìn)程維護(hù)一個(gè)打開文件表。打開文件后要為這個(gè)文件分配一個(gè)句柄號(hào)。在struct thread 結(jié)構(gòu)中加入: int FileNum; /打開文件數(shù) 限制進(jìn)程打開文件數(shù) struct list file_list; /打開文件列表 int maxfd; /句柄分配使用每打開一個(gè)文件就讓maxfd加1,關(guān)閉文件可以不減小。關(guān)聯(lián)文件句柄與文件指針的結(jié)構(gòu):(被鏈入file_list)struct f
13、ile_node int fd; struct list_elem elem; struct file *f;有了以上準(zhǔn)備,每打開一個(gè)文件都要新創(chuàng)建一個(gè)file_node結(jié)構(gòu),分配句柄,并把file_node加入file_list; 最后返回文件句柄就OK.SYS_CLOSE關(guān)閉文件 void IClose(struct intr_frame *f)一種是關(guān)閉一個(gè)文件。一種是進(jìn)程退出時(shí)關(guān)閉所有文件。從用戶棧中獲取要關(guān)閉文件的句柄。在用戶打開文件列表中找到對(duì)應(yīng)文件,以得到文件指針。調(diào)用file_close()函數(shù)關(guān)閉文件,釋放struct file_node。關(guān)閉所有文件自然是每一個(gè)都要關(guān)閉,釋
14、放了。 Debug here 3 weeksSYS_READ讀文件IRead()從用戶棧中獲得fd buffer size三個(gè)參數(shù)如果fd是標(biāo)準(zhǔn)輸入設(shè)備,則調(diào)用input_getc()如果fd是文件句柄由fd 從進(jìn)程打開文件表中得到文件指針調(diào)用file_read()函數(shù)從文件中讀數(shù)據(jù)。SYS_FILESIZE 獲取文件大小 IFileSize()從用戶棧中獲得fd由fd 從進(jìn)程打開文件表中得到文件指針調(diào)用file_len gth得到文件大小SYS_EXEC - 加載用戶程序 IExec()用戶程序通過SYS_EXEC這個(gè)系統(tǒng)調(diào)用創(chuàng)建子進(jìn)程。在IExec()函數(shù)中,分配一個(gè)頁,復(fù)制一份用戶提供的
15、用戶名。否則在后來分離參數(shù)時(shí),加入0時(shí)出現(xiàn)核心線程寫入用戶內(nèi)存空間的頁錯(cuò)誤。還要注意線程同步問題。在IExec()中調(diào)用process_execute()函數(shù)創(chuàng)建子進(jìn)程,但是從process_execute()得到了用戶進(jìn)程pid后,用戶程序并沒用加載。所以要等待用戶進(jìn)程被調(diào)度后調(diào)用了start_process()函數(shù)才能知道。 Start_process()函數(shù)真正加載用戶程序,可能會(huì)因?yàn)檎也坏匠绦蛭募騼?nèi)存不足等原因?qū)е录虞d失敗。 所以父進(jìn)程調(diào)用process_execute()后不能立即返回,要在一個(gè)信號(hào)量上等待sema_down(sema),直到start_process()函數(shù)中加載
16、用戶程序成功后再semp_up(sema)激活父進(jìn)程,激活父進(jìn)程后應(yīng)該立即掛起自己sema_down(sema),這里父進(jìn)程獲取子進(jìn)程狀態(tài)信息后,再出父進(jìn)程sema_up()激活子進(jìn)程。 如果父進(jìn)程創(chuàng)建了一個(gè)優(yōu)先級(jí)比自己高的子進(jìn)程,如果不這樣坐,start_process()函數(shù)每一次執(zhí)行sema_up(sema)后,父進(jìn)程還是不會(huì)被調(diào)度,而子進(jìn)程可以已經(jīng)運(yùn)行完畢,這樣父進(jìn)程就得不到子進(jìn)程的狀態(tài)了。在struct_thread結(jié)構(gòu)中加入semaphore SemaWaitSuccess;可以在父進(jìn)程的的這個(gè)信號(hào)量上等,也可是子進(jìn)程的SemaWaitSuccess上等。如果子進(jìn)程創(chuàng)建成功則返回p
17、id,失敗返回-1。SYS_WAIT等待函數(shù) IWait()主線程創(chuàng)建子進(jìn)程后,出于他與子進(jìn)程優(yōu)先級(jí)一樣,所以,二者交替執(zhí)行,這樣主線程就有可能先結(jié)束,這導(dǎo)致了一開始的test失敗。起初可以通過創(chuàng)建子進(jìn)程時(shí)提高子進(jìn)程優(yōu)先級(jí)或者在process_wait()中加入while(true)這樣的死循環(huán)來解決。后期要通過信號(hào)量同步。這個(gè)系統(tǒng)調(diào)用的需求: 父進(jìn)程創(chuàng)建子進(jìn)程后可能要等子進(jìn)程結(jié)束。Process_wait()要返回子進(jìn)程的返回值。情況有如下:父進(jìn)程調(diào)用process_wait()時(shí)子進(jìn)程還未結(jié)束,此進(jìn)父進(jìn)程將被掛起,等子進(jìn)程結(jié)束后再喚醒父進(jìn)程,父進(jìn)程再取得返回值。父進(jìn)程調(diào)用process_w
18、ait()時(shí)子進(jìn)程已經(jīng)結(jié)束,這就要求子進(jìn)程結(jié)束后應(yīng)該把返回值保存到父進(jìn)程的進(jìn)程控控制塊中。于是在struct thread要加入一個(gè)鏈表,struct list sons_ret;結(jié)構(gòu):struct ret_dataint pid;int ret;struct list_elem elem;這樣就能保存子進(jìn)程的返回值了。在struct thread結(jié)構(gòu)中加入 bool bWait; 表示進(jìn)程本身有沒有被父進(jìn)程等待。 在struct thread結(jié)構(gòu)中加入bool SaveData; 如果子進(jìn)程已經(jīng)把返回值保存到父進(jìn)程里了就設(shè)SaveData為true; SaveData應(yīng)該被初始化為false
19、;在struct thread結(jié)構(gòu)中加入struct thread *father;表示父線程。每創(chuàng)建一個(gè)子線程,都要在子線程中記錄父線程。信號(hào)量同步方法:在struct thread結(jié)構(gòu)中加入semaphore SemaWait;這里選擇在父進(jìn)程的SemaWait上等。這個(gè)等待會(huì)把父進(jìn)程的struct thread 進(jìn)程控制塊插入到SemaWait的list中去。要想同時(shí)等待多個(gè)進(jìn)程則不可能把父進(jìn)程插入到多個(gè)子進(jìn)程中去。當(dāng)然,這里的測(cè)試只能等一個(gè)子進(jìn)程,所以在父進(jìn)程和子進(jìn)程上等都可以。父進(jìn)程執(zhí)行process_wait(child_pid)后,可以由child_pid得到子進(jìn)程struct
20、thread 指針t。通過遍歷all_list比較pid實(shí)現(xiàn).如果在all_list沒有發(fā)現(xiàn)子進(jìn)程的進(jìn)程控制塊或者發(fā)現(xiàn)t-SaveData=true|t-status=THREAD_DYING;表示子進(jìn)程已經(jīng)結(jié)束,直接從自己的sons_ret鏈表中找到子進(jìn)程的返回值返回就OK.如果子進(jìn)程還在運(yùn)行,則執(zhí)行sema_down(t-father-SemaWait)把自己掛起,子進(jìn)程執(zhí)行完畢后,發(fā)現(xiàn)在bWait=true,自己被等待了,再釋放父進(jìn)程sema_up(SemaWait); 如果bWait=fale,則不用喚醒父進(jìn)程。父進(jìn)程被喚醒后,再從sons_ret鏈表中得到子進(jìn)程的返回值。每個(gè)子進(jìn)程只
21、能等一次,第二次等同一個(gè)子進(jìn)程只能返回-1.一個(gè)進(jìn)程結(jié)束時(shí),在process_exit()函數(shù)中,要釋放自己打開的所有文件,保存返回值到父進(jìn)程,輸出退出信息,如果有父進(jìn)程在等他就喚醒父進(jìn)程,釋放子進(jìn)程鏈表。SYS_SEEK -移動(dòng)文件指針 ISeek()從用戶棧中取出文件句fd柄要移動(dòng)的距離,把fd轉(zhuǎn)為文件指針,調(diào)用file_seek()函數(shù)移動(dòng)文件指針即可。SYS_REMOVE 刪除文件 IRemove從用戶棧中取出要?jiǎng)h除文件的文件名。調(diào)用filesys_remove()刪除文件。SYS_TELL 返回文件指針當(dāng)前位置 ITell()從用戶棧中取出文件句fd柄要移動(dòng)的距離,把fd轉(zhuǎn)為文件指針
22、,調(diào)用file_tell()函數(shù)得到指針位置。SYS_HALT 關(guān)機(jī) IHALT調(diào)用shutdown_power_off()函數(shù)關(guān)機(jī)用戶程序?qū)е马撳e(cuò)誤時(shí),會(huì)進(jìn)入page_fault()函數(shù),在exception.c中。 在page_fault()中加入 if(not_present|(is_kernel_vaddr(fault_addr)&user) ExitStatus(-1);來處理頁錯(cuò)誤。Task4 Denying Writes to Executables不能寫入可執(zhí)行文件在start_process函數(shù)中加入 t-FileSelf=filesys_open(token);file_d
23、eny_write(t-FileSelf);其中FileSelf變量是要在struct thread結(jié)構(gòu)中添加的。進(jìn)程退出時(shí)就解除:在process_exit()中加入 if(cur-FileSelf!=NULL) /撤銷對(duì)自己人deny_write file_allow_write(cur-FileSelf); file_close (cur-FileSelf); 注意:所有系統(tǒng)調(diào)用的返回值都放到用戶的eax寄存器中。取出參數(shù)時(shí)要對(duì)用戶棧指針作詳細(xì)的檢查,是否越界,越界則直接調(diào)用Exit_Status(-1)中止用戶進(jìn)程。用戶程序加載過程:(1)核心線程通過調(diào)用process_execute
24、(char *file_name);函數(shù)來創(chuàng)建用戶進(jìn)程。 File_name為要加載的文件名。這個(gè)函數(shù)中還調(diào)用了thread_create()函數(shù)為用戶進(jìn)程創(chuàng)建了一個(gè)線程。File_name 和一個(gè)叫start_process的函數(shù) 被傳遞給了thread_create(), thread_create()函數(shù)創(chuàng)建線程后就把線程放入ready_list()等待被調(diào)度;(2) 得到CPU后就開始start_process(void *file_name)函數(shù)。這個(gè)函數(shù)做了以下幾件事兒:根據(jù)file_name把用戶程序從硬盤調(diào)入內(nèi)存,還為其分配了虛擬內(nèi)存。注意這里要完成task2,不然文件名不正確
25、,就沒法打開文件。給用戶分配了棧空間3GB開始。向低字節(jié)增長。在這里要實(shí)現(xiàn)參數(shù)分離,并且把參數(shù)按規(guī)定放入用戶棧中。(3)通過內(nèi)嵌匯編 asm volatile (.)調(diào)用了用戶程序中的main()函數(shù)。(4)main()函數(shù)從棧中取出傳給他的參數(shù),執(zhí)行完畢后會(huì)調(diào)用系統(tǒng)調(diào)用exit(),Exit()函數(shù)又調(diào)用thread_exit()函數(shù),thread_exit()函數(shù)又調(diào)用process_exit()函數(shù),最后在thread_exit()函數(shù)中把即將退出的函數(shù)的進(jìn)程控制塊struct thread從all_list中remove掉,調(diào)用了進(jìn)程調(diào)度器schedule()函數(shù),調(diào)用下一下進(jìn)程執(zhí)行。
26、系統(tǒng)調(diào)用過程:在用戶程序使用一個(gè)系統(tǒng)調(diào)用,如printf();在必然會(huì)觸發(fā)一個(gè)30號(hào)中斷,正如src/lib/user/syscall.c文件中所述??梢妳?shù)個(gè)數(shù)不同,系統(tǒng)調(diào)用不同。 這個(gè)30號(hào)中斷調(diào)用之前,把系統(tǒng)調(diào)用號(hào)、用戶參數(shù)(0到3個(gè)不等)壓入棧中。然后開始執(zhí)行中斷程序,中斷程序又調(diào)用了syscall_handler(struct intr_frame *f)函數(shù),其中f是一個(gè)指向了用戶程序當(dāng)前運(yùn)行信息的的指針,其中就有用戶棧指針esp,所以在我們添加的系統(tǒng)調(diào)用中,就可以根據(jù)這個(gè)指針取出系統(tǒng)調(diào)用號(hào)和各個(gè)參數(shù)。系統(tǒng)調(diào)用結(jié)束后,要把返回值入如f-eax中.注意: 用戶棧中的各個(gè)參數(shù)并不連續(xù)存
27、放: 三個(gè)參數(shù)write(fd,buffer,size); int fd=*(esp+2); char *buffer=(char *)*(esp+6); unsigned size=*(esp+3); 兩個(gè)參數(shù)create(pFileName,size); bool ret=filesys_create(const char *)*(unsigned int *)f-esp+4),*(unsigned int *)f-esp+5); 一個(gè)參數(shù) exit(-1);cur-ret=*(int *)f-esp+1);附錄:Task2 參數(shù)傳遞代碼(紅色)Task3 系統(tǒng)調(diào)用(藍(lán)色)Task4 de
28、ny write (綠色)tid_tprocess_execute (const char *file_name) char *fn_copy; tid_t tid; /* Make a copy of FILE_NAME. Otherwise theres a race between the caller and load(). */ fn_copy = palloc_get_page (0); if (fn_copy = NULL) return TID_ERROR; strlcpy (fn_copy, file_name, PGSIZE); char *real_name, *save
29、_ptr; real_name = strtok_r (file_name, , &save_ptr); /* Create a new thread to execute FILE_NAME. */ tid = thread_create (real_name, PRI_DEFAULT, start_process, fn_copy); if (tid = TID_ERROR) palloc_free_page (fn_copy); return tid;/* A thread function that loads a user process and starts it running.
30、 */static voidstart_process (void *file_name_) char *file_name = file_name_; struct intr_frame if_; bool success; char *token=NULL, *save_ptr=NULL; token = strtok_r (file_name, , &save_ptr); / get real file name, use it in load() /* Initialize interrupt frame and load executable. */ memset (&if_, 0,
31、 sizeof if_); 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); struct thread *t=thread_current(); if (!success) palloc_free_page (file_name); t-tid=-1; sema_up(&t-SemaWaitSuccess); ExitStatus(-1);
32、 sema_up(&t-SemaWaitSuccess); t-FileSelf=filesys_open(token); file_deny_write(t-FileSelf); char *esp=(char *)if_.esp; char *arg256; /assume numbers of argument below 256 int i,n=0; for (; token != NULL;token = strtok_r (NULL, , &save_ptr) /copy the argument to user stack esp-=strlen(token)+1; /becau
33、se user stack increase to low addr. strlcpy(esp,token,strlen(token)+2); /copy param to user stack argn+=esp; while(int)esp%4make) /word align esp-; int *p=esp-4; *p-=0; /first 0 for(i=n-1;i=0;i-) /place the arguments pointers to stack *p-=(int *)argi; *p-=p+1; *p-=n; *p-=0; esp=p+1; if_.esp=esp; /se
34、t new stack top palloc_free_page (file_name); asm volatile (movl %0, %esp; jmp intr_exit : : g (&if_) : memory); NOT_REACHED ();Syscall.c中所有代碼:#include userprog/syscall.h#include threads/vaddr.h#include #include #include threads/interrupt.h#include threads/thread.h#include filesys/filesys.h#include
35、filesys/file.h#include devices/input.h#include process.h#include #include devices/shutdown.h#define MAXCALL 21#define MaxFiles 200#define stdin 1static void syscall_handler (struct intr_frame *);typedef void (*CALL_PROC)(struct intr_frame*);CALL_PROC pfnMAXCALL;void IWrite(struct intr_frame*);void I
36、Exit(struct intr_frame *f);void ExitStatus(int status);void ICreate(struct intr_frame *f);void IOpen(struct intr_frame *f);void IClose(struct intr_frame *f);void IRead(struct intr_frame *f);void IFileSize(struct intr_frame *f);void IExec(struct intr_frame *f);void IWait(struct intr_frame *f);void IS
37、eek(struct intr_frame *f);void IRemove(struct intr_frame *f);void ITell(struct intr_frame *f);void IHalt(struct intr_frame *f);struct file_node *GetFile(struct thread *t,int fd);voidsyscall_init (void) intr_register_int (0x30, 3, INTR_ON, syscall_handler, syscall); int i; for(i=0;iesp) ExitStatus(-1
38、); int No=*(int *)(f-esp); if(No=MAXCALL|MAXCALLesp; if(!is_user_vaddr(esp+7) ExitStatus(-1); int fd=*(esp+2); /文件句柄 char *buffer=(char *)*(esp+6); /要輸出人緩沖 unsigned size=*(esp+3); /輸出內(nèi)容大小。 if(fd=STDOUT_FILENO) /標(biāo)準(zhǔn)輸出設(shè)備 putbuf (buffer, size); f-eax=0; else /文件 struct thread *cur=thread_current(); stru
39、ct file_node *fn=GetFile(cur,fd); /獲取文件指針 if(fn=NULL) f-eax=0; return; f-eax=file_write(fn-f,buffer,size);/寫文件 void IExit(struct intr_frame *f) /一個(gè)參數(shù) 正常退出時(shí)使用 if(!is_user_vaddr(int *)f-esp)+2) ExitStatus(-1); struct thread *cur=thread_current(); cur-ret=*(int *)f-esp+1); f-eax=0; thread_exit();void E
40、xitStatus(int status) /非正常退出時(shí)使用 struct thread *cur=thread_current(); cur-ret=status; thread_exit();void ICreate(struct intr_frame *f) /兩個(gè)參數(shù) if(!is_user_vaddr(int *)f-esp)+6) ExitStatus(-1); if(const char *)*(unsigned int *)f-esp+4)=NULL) f-eax=-1; ExitStatus(-1); bool ret=filesys_create(const char *
41、)*(unsigned int *)f-esp+4),*(unsigned int *)f-esp+5); f-eax=ret;void IOpen(struct intr_frame *f) if(!is_user_vaddr(int *)f-esp)+2) ExitStatus(-1); struct thread *cur=thread_current(); const char *FileName=(char *)*(int *)f-esp+1); if(FileName=NULL) f-eax=-1; ExitStatus(-1); struct file_node *fn=(str
42、uct file_node *)malloc(sizeof(struct file_node); fn-f=filesys_open(FileName); if(fn-f=NULL| cur-FileNum=MaxFiles)/ fn-fd=-1; else fn-fd=+cur-maxfd; f-eax=fn-fd; if(fn-fd=-1) free(fn); else cur-FileNum+; list_push_back(&cur-file_list,&fn-elem); void IClose(struct intr_frame *f) if(!is_user_vaddr(int
43、*)f-esp)+2) ExitStatus(-1); struct thread *cur=thread_current(); int fd=*(int *)f-esp+1); f-eax=CloseFile(cur,fd,false);int CloseFile(struct thread *t,int fd,int bAll) struct list_elem *e,*p; if(bAll) while(!list_empty(&t-file_list) struct file_node *fn = list_entry (list_pop_front(&t-file_list), st
44、ruct file_node, elem); file_close(fn-f); free(fn); t-FileNum=0; return 0; for (e = list_begin (&t-file_list); e != list_end (&t-file_list);) struct file_node *fn = list_entry (e, struct file_node, elem); if(fn-fd=fd) list_remove(e); if(fd=t-maxfd) t-maxfd-; t-FileNum-; file_close(fn-f); free(fn); return 0; void IRead(struct intr_frame *f) int *esp=(int *)f-esp; if(!is_user_vaddr(esp+7) ExitStatus(-1); int f
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國波紋管帶數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 現(xiàn)代家居裝飾的綠色環(huán)保理念
- 2024年銅仁市人民醫(yī)院同一后勤公司招聘招聘理貨員筆試真題
- 2024年瓊海市考核招聘事業(yè)單位專業(yè)技術(shù)人才考試真題
- 2024年寧波北部綜合保供基地開發(fā)有限公司招聘考試真題
- 2024年河南洛陽偃師區(qū)婦幼保健院招聘筆試真題
- 2024年黑龍江省選調(diào)應(yīng)屆 到基層培養(yǎng)鍛煉工作考試真題
- 技術(shù)合同范本
- 2024年第八師石河子市總醫(yī)院招聘考試真題
- 光學(xué)儀器采購合同
- 華為全屋智能試題
- 品牌策劃大賽獲獎(jiǎng)案例范文
- 自媒體賬號(hào)合作運(yùn)營協(xié)議
- 煙草專賣零售許可證新辦申請(qǐng)表
- 數(shù)學(xué)大觀 知到智慧樹網(wǎng)課答案
- 旅游學(xué)概論(郭勝 第五版) 課件 第5、6章 旅游業(yè)、旅游市場(chǎng)
- 安全隱患規(guī)范依據(jù)查詢手冊(cè)22大類12萬字
- 2024年杭州科技職業(yè)技術(shù)學(xué)院單招職業(yè)技能測(cè)試題庫及答案解析
- (2024年)精美網(wǎng)絡(luò)安全講座
- 2023屆新高考英語語法填空分類強(qiáng)化100題 語法填空之現(xiàn)在分詞過去分詞100題(思維導(dǎo)圖+三年真題+模擬)
- JGJ79-2012 建筑地基處理技術(shù)規(guī)范
評(píng)論
0/150
提交評(píng)論