pintospro2項(xiàng)目2用戶(hù)程序_第1頁(yè)
pintospro2項(xiàng)目2用戶(hù)程序_第2頁(yè)
pintospro2項(xiàng)目2用戶(hù)程序_第3頁(yè)
pintospro2項(xiàng)目2用戶(hù)程序_第4頁(yè)
pintospro2項(xiàng)目2用戶(hù)程序_第5頁(yè)
已閱讀5頁(yè),還剩28頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、實(shí)用標(biāo)準(zhǔn)文檔Pi ntos project2作者:西安電子科技大學(xué)王永剛 QQ:357543420這個(gè)項(xiàng)目將使pintos可以加載并執(zhí)行用戶(hù)程序,并且為用戶(hù)程序 提供系統(tǒng)調(diào)用。Project2需要完成的的任務(wù)有四個(gè):Taskl Process Termin ati on Messages進(jìn)程終止信息Task2 Argume nt Pass ing參數(shù)傳遞Task3 System Calls 系統(tǒng)調(diào)用Task4 Den yi ng Writes to Executables不能寫(xiě)入可執(zhí)行文件Task1: Process Termin ati on Messages進(jìn)程終止信息要求:1. 在進(jìn)程結(jié)

2、束時(shí)輸出退出代碼(就是main函數(shù)的返回值,或者 異常退出代碼。注意:用戶(hù)進(jìn)程結(jié)束時(shí)輸入退出代碼,核心線(xiàn)程返回時(shí)不輸入。 輸出格式被規(guī)定如下:printf (“%s: exit(%d)n ”,.);實(shí)現(xiàn)方法:1. 既然要打印返回值,就得用一個(gè)變量保存返回值,于是在 struct thread結(jié)構(gòu)中加入一個(gè)變量回保存返回值:in t ret;在init_thread()函數(shù)中初始化為0(這里可以不用初始化)。2. 在線(xiàn)程退出里要保存其返回值到ret中,這個(gè)將在系統(tǒng)調(diào)用里的exit函數(shù)中保存,這里先不考慮。在什么地方加入printf() 呢?每個(gè)線(xiàn)程結(jié)束后,都要調(diào)用thread_exit()函數(shù),

3、如果是加載 了用戶(hù)進(jìn)程,在thread_exit() 函數(shù)中還會(huì)調(diào)用 process_exit() 函數(shù),在process_exit() 函數(shù)中,如果是用 戶(hù)進(jìn)程,那么其頁(yè)表一定不為NULL,而核心進(jìn)程頁(yè)表一定為NULL,即只有用戶(hù)進(jìn)程退出時(shí)if(pd!=NULL) 就會(huì)成立,所 以在大括號(hào)中加入:printf (“ %s: exit(%d)n ” ,cur-name,cur-ret);其中 cur=thread_current();即當(dāng)前線(xiàn)程的 struct thread指針。TASK1 OK-TASK2Argume nt Passi ng參數(shù)傳遞要求:1. 分離從命令行傳入的文件名和各個(gè)參

4、數(shù)。2. 按照C函數(shù)調(diào)用約定,把參數(shù)放入棧中。實(shí)現(xiàn)方法:1. 分離參數(shù)的方法:用string.h中的strtok_r() 函數(shù),在string.c中有詳細(xì)的說(shuō)明。2. 在 process_execute() 函數(shù)中,因?yàn)?thread_create() 需要一個(gè)線(xiàn) 程名,此時(shí)應(yīng)該傳遞給它文件名(不帶參數(shù))。可如下處理:char *real_ name, *save_ptr;real_n ame = strtok_r (file_ name, , & save_ptr);tid = thread_create (real_ name, PRI_DEFAULTstart_process, fn_c

5、opy);(3) 在start_process() 函數(shù)中,再次分離參數(shù),放入棧中。由于在process_execute()對(duì)file_name作了復(fù)制,文件名并未丟失, 但是要注意,無(wú)論加載用戶(hù)程序成功還是失敗,都得釋放filename所占用的一個(gè)頁(yè)的空間(Debug here 3 weeks)。 注意:傳給Load() 函數(shù)的參數(shù)也只能有文件名,所以在load()函數(shù)前要分離出文件名: char *toke n=NULL, *save_ptr二NULL;toke n = strtok_r (file_ name, , & save_ptr);success = load (toke n,

6、& f_.eip, & f_.esp);參數(shù)放置的一種方法:(1) 找到用戶(hù)棧指針:在 start_process() 函數(shù)中有 struct intr_frame if_; 這樣一個(gè) 結(jié)構(gòu),其中有一個(gè)成員if_.esp,這就是用戶(hù)棧指針,在load()函數(shù)中為其賦值,分配了棧空間(2) 調(diào)用strtok_r 分離出一個(gè)個(gè)參數(shù)(就是一個(gè)個(gè)字符串了),把 每個(gè)字符串都復(fù)制到用戶(hù)棧中,并把他在棧中的位置記錄到一個(gè)數(shù)組 中,以備下一步使用。注意:棧是向下增長(zhǎng),而字符串是向上增長(zhǎng)。char *esp=(char *)if_.esp;char *arg256;/assume nu mbers of ar

7、gume nt below 256int i,n=0;for (; token != NULL;token = strtok_r (NULL, , &save_ptr)esp-=strle n( toke n)+1; /because user stack in crease 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(i nt)esp%4make) /word alig nesp-;/注意:

8、棧是向下增長(zhǎng),所以這里是一而不是+;(4) 要將第(2)步保存下的指針逆序放入棧中。按照C約定,先要放入一個(gè)0,以防沒(méi)有參數(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 argume nts poin ters to stack*p-=(i nt *)argi;(5) 放入 argc,argv*p-=p+1;*p-=n;*p-=0;esp=p+1;(6) 讓用戶(hù)棧指針指向新的棧頂if_.esp=esp如下圖擺放。如果命令行是:/bin/ls - I foo barThe talile be

9、low shows the state of the stack and the relevant registers right before the beginning of the user program, assuming PHYS_BASE is OxcOOOOOOO:AddreFisNameDataTypoOxbffffffcargv3.Jbar0char4OxbffffffSargv2.-1foo0char4OxbffffffSargvl.4-l0:char3Oxbfffffedargv 0JVbln/lflXO*char8OxbfffffGCword-ahgn0uint8_t

10、OxbfffffeSargv40char +0xbfffffe4argv 3Oibffffffcchar *OxbfffffeOargv QxbffffffBchar +OxbfffffdeargvlOzbffffffSchar *OxbfffffdSargv 0Oxbfffffedchar *0xbfffffd4argvOxbfffffdflchar *+OxbfffffdOaxgc1intOxbfffffccfetnri address0void (*)()In this exam pie f die stajck pointer would be inilialized lu Oxbf

11、f f f f cc.As shown above, youi code should start the slack al ihe very top of the user virtual address spact. in the page just hcluw virtual address PHYS_BASE (defined in完整代碼見(jiàn)附錄!TASK 3 system call 系統(tǒng)調(diào)用要求:(1) 實(shí)現(xiàn)以下系統(tǒng)調(diào)用:pfnSY S_WRITEIWrite;/pri ntf和寫(xiě)文件需要。pfnSY S_EXI=IExit;/退出時(shí)return后調(diào)用pfnSY S_CREA=ECr

12、eate;/創(chuàng)建文件pfnSY S_OPENOpe n;/打開(kāi)文件pfnSY S_CLOSSCIose;/關(guān)閉文件pfnSY S_READRead;/讀文件pfn SY S_FILESIZf=IFileSize; /返回文件大小pfnSY S_EXE|CIExec;/加載用戶(hù)程序pfnSYS_WA|=IWait;/等待子進(jìn)程結(jié)束pfnSY S_SEE|KISeek;/移動(dòng)文件指針pfnSY S_REMOVE?emove; /刪除文件pfnSY S_TEL=ITell;/返回文件指針位置pfnSY S_HAL|TIHalt;/關(guān)機(jī)要想完成以上系統(tǒng)調(diào)用,還要明白系統(tǒng)調(diào)用的機(jī)制,見(jiàn)后邊。參考文件有:

13、src/lib/user/syscall.c了解每個(gè)系統(tǒng)調(diào)用的形式。了解每個(gè)系統(tǒng)調(diào)用號(hào)。src/lib/syscall-nr.h實(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 in tr_frame*);CALL_PROC pfnMAXCALL;voidsyscall_ in it (void)intr_register_int (0x30, 3, INTR_ON, sys

14、call_handler, syscall);int i;for(i=0;iesp)ExitStatus(-1);int No=*(int *)(f-esp);if(No=MAXCALL|MAXCALLret=status; /保存返回值。thread_exit();SYS_CREAT創(chuàng)建文件 void ICreate(struct intr_frame *f)取出僅有的一個(gè)參數(shù)一文件名。調(diào)用 filesys_create() 函數(shù)。保存返回值。4SYS_OPEN-打開(kāi)文件 void IOpen(struct intr_frame *f)取出文件名。調(diào)用filesys_open()函數(shù)打開(kāi)文件

15、。這里需要為每個(gè)進(jìn)程維護(hù)一個(gè)打開(kāi)文件表。打開(kāi)文件后要為這個(gè)文件分配一個(gè)句柄號(hào)。在 struct thread結(jié)構(gòu)中加入:int FileNum;/struct list file_list; /打開(kāi)文件數(shù)限制進(jìn)程打開(kāi)文件數(shù)打開(kāi)文件列表int maxfd;/句柄分配使用每打開(kāi)一個(gè)文件就讓 maxfd加1關(guān)閉文件可以不減小。關(guān)聯(lián)文件句柄與文件指針的結(jié)構(gòu):(被鏈入file_list )struct file_ nodeint fd;struct list_elem elem;struct file *f;;有了以上準(zhǔn)備,每打開(kāi)一個(gè)文件都要新創(chuàng)建一個(gè)file_node 結(jié)構(gòu),分配句柄,并把file_n

16、ode 加入file_list;最后返回文件句柄就 0K. SYS_CLOSE關(guān)閉文件 void IClose(struct intr_frame *f)一種是關(guān)閉一個(gè)文件。一種是進(jìn)程退出時(shí)關(guān)閉所有文件從用戶(hù)棧中獲取要關(guān)閉文件的句柄。在用戶(hù)打開(kāi)文件列表中找到對(duì)應(yīng)文件,以得到文件指針。調(diào)用file_close()函數(shù)關(guān)閉文件,釋放 struct file_ node。關(guān)閉所有文件自然是每一個(gè)都要關(guān)閉,釋放了。Debug here 3 weeks SYS_READ讀文件 IRead()從用戶(hù)棧中獲得fd buffer size三個(gè)參數(shù)如果fd是標(biāo)準(zhǔn)輸入設(shè)備,則調(diào)用input_getc() 如果fd

17、是文件句柄由fd從進(jìn)程打開(kāi)文件表中得到文件指針調(diào)用file_read()函數(shù)從文件中讀數(shù)據(jù)。 SYS_FILESIZE - 獲取文件大小 IFileSize()從用戶(hù)棧中獲得fd由fd從進(jìn)程打開(kāi)文件表中得到文件指針調(diào)用file_len gth 得到文件大小 SY S_EXEC -加載用戶(hù)程序IExec()用戶(hù)程序通過(guò)SYS_EXE這個(gè)系統(tǒng)調(diào)用創(chuàng)建子進(jìn)程。在IExec()函數(shù)中,分配一個(gè)頁(yè),復(fù)制一份用戶(hù)提供的用戶(hù)名。否則在后來(lái)分離參數(shù)時(shí),加入0 時(shí)出現(xiàn)核心線(xiàn)程寫(xiě)入用戶(hù)內(nèi)存空間的頁(yè)錯(cuò)誤。還要注意線(xiàn)程同步問(wèn)題。在IExec()中調(diào)用 process_execute()函數(shù)創(chuàng)建子進(jìn)程,但是從 proc

18、ess_execute()得到了用戶(hù)進(jìn)程pid后,用戶(hù)程序并沒(méi)用加載。所以要等待用戶(hù)進(jìn)程被調(diào)度后一調(diào)用了 start_process()函數(shù)才能知 道。Start_process()函數(shù)真正加載用戶(hù)程序,可能會(huì)因?yàn)檎也坏匠绦蛭募騼?nèi)存不足等原因?qū)е录虞d失敗。 所以父進(jìn)程調(diào)用 process_execute()后不能立即返回,要在一個(gè)信號(hào)量上等待 sema_down(sema)直到start_process() 函數(shù)中加載用戶(hù)程序成功 后再semp_up(sema激活父進(jìn)程,激活父進(jìn)程后應(yīng)該立即掛起自己一 sema_dow n( sema)這里父進(jìn)程獲取子進(jìn)程狀態(tài)信息后,再出父進(jìn)程 sema_u

19、p()激活子進(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)建成功則返回pid,失敗返回-1。SY S_WA等待函數(shù) IWait()主線(xiàn)程創(chuàng)建子進(jìn)程后,出于他與子進(jìn)程優(yōu)先級(jí)一樣,所以,二者交替執(zhí)行,這樣主線(xiàn)程就有可能先結(jié)束,這導(dǎo)致了

20、一開(kāi)始的test失敗。起初可以通過(guò)創(chuàng)建子進(jìn)程時(shí)提高子進(jìn)程優(yōu)先級(jí)或者在 process_wait()中加入while(true) 這樣的死循環(huán)來(lái)解決。后期要通 過(guò)信號(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_wait()時(shí)子進(jìn)程已經(jīng)結(jié)束,這 就要求子進(jìn)程結(jié)束后應(yīng)該把返回值保存到父進(jìn)程的進(jìn)程控控制塊中。于是在 struct thread要加入一個(gè)鏈表,struc

21、t 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)程本身有沒(méi)有被父進(jìn)程等待。在struct thread 結(jié)構(gòu)中加入bool SaveData;如果子進(jìn)程已經(jīng)把 返回值保存到父進(jìn)程里了就設(shè) SaveData為true; SaveData 應(yīng)該被 初始化為false;在struct thread結(jié)構(gòu)中加入struct thread *father; 表示父線(xiàn)程。每創(chuàng)建一個(gè)子線(xiàn)程,都要在子線(xiàn)程中記錄父線(xiàn)程。

22、信號(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 thread 指針t。通過(guò)遍歷all_list 比較pid實(shí)現(xiàn). 如果在all_list 沒(méi)有發(fā)現(xiàn)子進(jìn)程的進(jìn)程控制塊或者發(fā)現(xiàn) t

23、-SaveData=true|t-status=THREAD_D YING;表示子進(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)程被喚醒后,再?gòu)膕ons_ret鏈表中得到子進(jìn)程的返回值。每個(gè)子進(jìn)程只能等一次,第二次等同一個(gè)子進(jìn)程只能返回-1.一個(gè)進(jìn)程結(jié)束時(shí),在 process_exit()函數(shù)中,要釋放自己打

24、開(kāi) 的所有文件,保存返回值到父進(jìn)程,輸出退出信息,如果有父進(jìn)程在 等他就喚醒父進(jìn)程,釋放子進(jìn)程鏈表。SY S_SEEK -移動(dòng)文件指針I(yè)Seek()從用戶(hù)棧中取出文件句fd柄要移動(dòng)的距離,把fd轉(zhuǎn)為文件指針,調(diào)用file_seek()函數(shù)移動(dòng)文件指針即可。SY S_REMOVE 除文件 IRemove從用戶(hù)棧中取出要?jiǎng)h除文件的文件名調(diào)用filesys_remove() 刪除文件。垃S YS_TELL返回文件指針當(dāng)前位置ITell()從用戶(hù)棧中取出文件句fd柄要移動(dòng)的距離,把fd轉(zhuǎn)為文件指針,調(diào)用file_tell()函數(shù)得到指針位置。 SY S_HALT 關(guān)機(jī) IHALT調(diào)用 shutdown

25、_power_off()函數(shù)關(guān)機(jī)用戶(hù)程序?qū)е马?yè)錯(cuò)誤時(shí),會(huì)進(jìn)入page_fault()函數(shù),在exception.c 中。在page_fault() 中加入if(no t_prese nt|(is_ker nel_vaddr(fault_addr)&user)ExitStatus(-1);來(lái)處理頁(yè)錯(cuò)誤。Task4 Denying Writes to Executables不能寫(xiě)入可執(zhí)行文件在start_process 函數(shù)中加入t-FileSelf=filesys_ope n(toke n);file_de ny_write(t-FileSelf);其中FileSelf 變量是要在 struct

26、 thread結(jié)構(gòu)中添加的。進(jìn)程退出時(shí)就解除:在 process_exit() 中加入if(cur-FileSelf!=NULL) /撤銷(xiāo)對(duì)自己人 den y_writefile_allow_write(cur-FileSelf);file_close (cur-FileSelf);注意:所有系統(tǒng)調(diào)用的返回值都放到用戶(hù)的eax寄存器中。取出參數(shù)時(shí)要對(duì)用戶(hù)棧指針作詳細(xì)的檢查,是否越界,越界則直接調(diào)用Exit_Status(-1) 中止用戶(hù)進(jìn)程用戶(hù)程序加載過(guò)程:(1) 核心線(xiàn)程通過(guò)調(diào)用 process_execute(char *file_name);函數(shù)來(lái)創(chuàng)建用戶(hù)進(jìn)程。Filename為要加載的

27、文件名。這個(gè) 函數(shù)中還調(diào)用了 thread_create()函數(shù)為用戶(hù)進(jìn)程創(chuàng)建了一 個(gè)線(xiàn)程。File_name和一個(gè)叫start_process 的函數(shù) 被傳遞 給了 thread_create(), thread_create()函數(shù)創(chuàng)建線(xiàn)程后就把線(xiàn)程放入ready_list()等待被調(diào)度;(2) 得到 CPU后就開(kāi)始 start_process(void *file_name) 函 數(shù)。這個(gè)函數(shù)做了以下幾件事兒: 根據(jù)file_name把用戶(hù)程序從硬盤(pán)調(diào)入內(nèi)存,還為其分配 了虛擬內(nèi)存。注意這里要完成task2 ,不然文件名不正確,就 沒(méi)法打開(kāi)文件。 給用戶(hù)分配了??臻g3GB開(kāi)始。向低字節(jié)增

28、長(zhǎng)。在這里要實(shí)現(xiàn)參數(shù)分離,并且把參數(shù)按規(guī)定放入用戶(hù)棧中。(3) 通過(guò)內(nèi)嵌匯編asm volatile ( .)調(diào)用了用戶(hù)程序中的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í)行。系統(tǒng)調(diào)用過(guò)程:在用戶(hù)程序使用一個(gè)系統(tǒng)調(diào)用,如

29、printf();在必然會(huì)觸發(fā)一個(gè)30號(hào)中斷,正如src/lib/user/syscall.c 文件中所述??梢?jiàn)參數(shù)個(gè)數(shù) 不同,系統(tǒng)調(diào)用不同。這個(gè)30號(hào)中斷調(diào)用之前,把系統(tǒng)調(diào)用號(hào)、用戶(hù)參數(shù)(0到3個(gè)不等)壓入棧中。然后開(kāi)始執(zhí)行中斷程序,中斷程 序又調(diào)用了 syscall_handler(struct intr_frame *f)函數(shù),其中 f是一個(gè)指向了用戶(hù)程序當(dāng)前運(yùn)行信息的的指針,其中就有用戶(hù)棧指針esp,所以在我們添加的系統(tǒng)調(diào)用中,就可以根據(jù)這個(gè)指針取出系統(tǒng)調(diào) 用號(hào)和各個(gè)參數(shù)。系統(tǒng)調(diào)用結(jié)束后,要把返回值入如f-eax中.用戶(hù)棧中的各個(gè)參數(shù)并不連續(xù)存放:三個(gè)參數(shù) write(fd,buffe

30、r,size);int fd=*(esp+2);char *buffer=(char *)*(esp+6);un sig ned size=*(esp+3);兩個(gè)參數(shù) create(pFileName,size);bool ret=filesys_create(c onst char *)*( un sig ned int *)f-esp+4),*(unsigned int *)f-esp+5);一個(gè)參數(shù) exit(-1);cur-ret=*(i nt *)f-esp+1);附錄:Task2參數(shù)傳遞代碼(紅色)Task3系統(tǒng)調(diào)用(藍(lán)色)Task4 deny write ( 綠色)tid_tpr

31、ocess_execute (const char *file_name)char *fn_copy;tid_t tid;/* Make a copy of FILE_NAME.Otherwise theres a race betwee n 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_ptr;real_n ame = strtok_r

32、(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 itrunning. */static voidstart_process (v

33、oid *file_name_)char *file_ name = file_ name_;struct in tr_frame if_;bool success;char *toke n=NULL, *save_ptr=NULL;toke n = strtok_r (file _n ame, , &save_ptr); / get real file n ame, use itin load()/* Initialize interrupt frame and load executable. */memset (&if_, 0, sizeof if_);if_.gs = if_.fs =

34、 if_.es = if_.ds = if_.ss = SEL_UDSEG;if_.cs = SEL_UCSEG;if_.eflags = FLAGF | FLAG_MBS;success = load (token , &if_.eip, &if_.esp);struct thread *t=thread_curre nt();if (!success)palloc_free_page (file_ name);t-tid=-1;sema_up( &t-SemaWaitSuccess);ExitStatus(-1);sema_up(&t-SemaWaitSuccess);t-FileSelf

35、=filesys_ope n( toke n);file_de ny_write(t-FileSelf);char *esp=(char *)if_.esp;char *arg256;/assume nu mbers of argume nt below 256int i,n=0;for (; token != NULL;token = strtok_r (NULL, , &save_ptr) /copy theargume nt to user stackesp-=strle n(toke n)+1;/because user stackin crease to low addr.strlc

36、py(esp,token,strlen(token)+2);/copyparam to user stackargn+=esp;/word alig nwhile(i nt)esp%4make) esp-;int *p=esp-4;/first 0/place the argume nts poin ters to stack*p_=0;for( i=n-1;i=0;i_)*p-=(i nt *)argi;*p_=p+1;*p-=n;*p-=0;esp=p+1;if_.esp=esp;/set new stack toppalloc_free_page (file_ name);asm vol

37、atile (movl %0, %esp; jmp intr_exit : : g (&if_) : memory); NOT_REACHED ();Syscall.c中所有代碼:#in clude userprog/syscall.h#in clude threads/vaddr.h#in clude #in clude #in clude threads/i nterrupt.h#in clude threads/thread.h#i nclude filesys/filesys.h#in clude filesys/file.h#in clude devices/i nput.h#in

38、clude process.h#in clude #in clude devices/shutdow n.h#defi ne MAXCALL 21#defi ne MaxFiles 200#defi ne std in 1static void syscall_ha ndler (struct in tr_frame *);typedef void (*CALL_PROC)(struct in tr_frame*);CALL_PROC pfnMAXCALL;void IWrite(struct in tr_frame*);void IExit(struct in tr_frame *f);vo

39、id ExitStatus(i nt status);void ICreate(struct in tr_frame *f);void IOpe n(struct in tr_frame *f);void IClose(struct in tr_frame *f);void IRead(struct i ntr_frame *f);void IFileSize(struct i ntr_frame *f);void IExec(struct in tr_frame *f);void IWait(struct in tr_frame *f);void ISeek(struct i ntr_fra

40、me *f);void IRemove(struct in tr_frame *f);void ITell(struct in tr_frame *f);void IHalt(struct in tr_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);int No=*(i nt *)(

41、f-esp);if(No=MAXCALL|MAXCALLesp;文件句柄要輸出人緩沖 輸出內(nèi)容大小。if(!is_user_vaddr(esp+7) ExitStatus(-1);int fd=*(esp+2);/char *buffer=(char *)*(esp+6); / un sig ned size=*(esp+3);/文案大全if(fd=STDOUT_FILENO) /標(biāo)準(zhǔn)輸出設(shè)備putbuf (buffer, size);f-eax=0; else/文件struct thread *cur=thread_curre nt();struct file_node *fn=GetFil

42、e(cur,fd); /獲取文件指針if(fn=NULL) f-eax=0;return;f-eax=file_write(fn-f,buffer,size);寫(xiě)文件一個(gè)參數(shù)正常退非正常退出時(shí)使用兩個(gè)參數(shù)*)*( un sig nedintvoid IExit(struct intr_frame *f) / 出時(shí)使用if(!is_user_vaddr(i nt *)f-esp)+2)ExitStatus(-l);struct thread *cur=thread_curre nt();cur-ret=*(i nt *)f-esp+1);f-eax=0;thread_exit();void Ex

43、itStatus(int status) /struct thread *cur=thread_curre nt();cur-ret=status;thread_exit();void ICreate(struct intr_frame *f) /if(!is_user_vaddr(i nt *)f-esp)+6)ExitStatus(-1);if(const char *)*(unsigned int *)f-esp+4)=NULL)f-eax=-1;ExitStatus(-1);boolret=filesys_create(c onstchar*)f-esp+4),*(unsigned i

44、nt *)f-esp+5);f-eax=ret;void IOpen(struct intr_frame *f)if(!is_user_vaddr(i nt *)f-esp)+2)ExitStatus(-l);struct thread *cur=thread_curre nt();const char *FileName=(char *)*(int *)f-esp+1);if(FileName=NULL)f-eax=-1;ExitStatus(-1);struct file_ node *fn=(struct file_ node *)malloc(sizeof(struct file_ n

45、o de);fn-f=filesys_ope n( 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);elsecur-FileNum+;list_push_back (&cur-file_list,& fn-elem);void IClose(struct intr_frame *f)if(!is_user_vaddr(i nt *)f-esp)+2)ExitStatus(-1);struct thread *cur=thread

46、_curre nt();int fd=*(i nt *)f-esp+1); f-eax=CloseFile(cur,fd,false);int CloseFile(struct thread *t,int fd,int bAll)struct list_elem *e,*p;if(bAII)while(!list_empty(&t-file_list)struct file_ node *fn = list_e ntry (list_pop_fr ont(&t-fileist), struct file_ no de, elem);file_close(fn-f);free(fn);t-Fil

47、eNum=O;return 0;for (e = list_begin (&t-file_list); e != list_end (&t-file_list);)struct file_ node *fn = list_e ntry (e, struct file_ no de, 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=(i nt *)f-esp;i

48、f(!is_user_vaddr(esp+7) ExitStatus(-1);int fd=*(esp+2);char *buffer=(char *)*(esp+6); un sig ned size=*(esp+3);if(buffer=NULL|!is_user_vaddr(buffer+size)f-eax=_1;ExitStatus(-l);struct thread *cur=thread_curre nt(); struct file_ node *fn=NULL;從標(biāo)準(zhǔn)輸入設(shè)備讀從文件讀獲取文件指針un sig ned int i; if(fd=STDIN_FILENO)/for(i=0;ieax=-1;return; f-eax=file_read(fn-f,buffer,size);struct file_node *GetFile(struct thread *t,int fd)/依據(jù)文件句柄從進(jìn)程打開(kāi)文件表中找到文件指針struct list_elem *e;for(e = list_begi n(&t-fileist);e !=list_

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論