pintos-pro2-項目2-用戶程序_第1頁
pintos-pro2-項目2-用戶程序_第2頁
pintos-pro2-項目2-用戶程序_第3頁
pintos-pro2-項目2-用戶程序_第4頁
pintos-pro2-項目2-用戶程序_第5頁
已閱讀5頁,還剩42頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、精選優(yōu)質文檔-傾情為你奉上Pintos project2作者:西安電子科技大學王永剛 QQ:這個項目將使pintos可以加載并執(zhí)行用戶程序,并且為用戶程序提供系統(tǒng)調用。Project2 需要完成的的任務有四個: Task1 Process Termination Messages進程終止信息 Task2 Argument Passing 參數傳遞 Task3 System Calls 系統(tǒng)調用 Task4 Denying Writes to Executables不能寫入可執(zhí)行文件Task1: Process Termination Messages進程終止信息要求: 1.在進程結束時輸出退出

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

3、用戶進程,在thread_exit()函數中還會調用process_exit()函數, 在process_exit()函數中,如果是用戶進程,那么其頁表一定不為NULL,而核心進程頁表一定為NULL,即只有用戶進程退出時if(pd!=NULL) 就會成立,所以在大括號中加入:printf (“%s: exit(%d)n”,cur->name,cur->ret);其中cur=thread_current();即當前線程的struct thread 指針。TASK1 OKTASK2 Argument Passing 參數傳遞要求:1. 分離從命令行傳入的文件名和各個參數。2. 按照C函

4、數調用約定,把參數放入棧中。實現方法:1.分離參數的方法:用string.h中的strtok_r()函數,在string.c中有詳細的說明。2.在process_execute()函數中,因為thread_create()需要一個線程名,此時應該傳遞給它文件名(不帶參數)??扇缦绿幚恚篶har *real_name, *save_ptr; real_name = strtok_r (file_name, " ", &save_ptr); tid = thread_create (real_name, PRI_DEFAULT, start_process, fn_co

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

6、token, &if_.eip, &if_.esp);參數放置的一種方法:(1)找到用戶棧指針:在start_process()函數中有struct intr_frame if_; 這樣一個結構,其中有一個成員if_.esp,這就是用戶棧指針,在load()函數中為其賦值,分配了??臻g。(2)調用strtok_r 分離出一個個參數(就是一個個字符串了),把每個字符串都復制到用戶棧中,并把他在棧中的位置記錄到一個數組中,以備下一步使用。注意:棧是向下增長,而字符串是向上增長。 char *esp=(char *)if_.esp; char *arg256; /assume num

7、bers of argument below 256 int i,n=0; for (; token != 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)要加入一個雙字的對齊,因為是32位的,所以就是四字節(jié)對齊。while(int)esp%4mak

8、e) /word align esp-; /注意:棧是向下增長,所以這里是而不是+;(4)要將第(2)步保存下的指針逆序放入棧中。按照C約定,先要放入一個0,以防沒有參數。 int *p=esp-4; *p-=0; 然后依次放入參數n的地址,參數n-1的地址 參數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如下圖擺放。 如果

9、命令行是:/bin/ls l foo bar完整代碼見附錄!TASK 3 system call 系統(tǒng)調用要求:(1)實現以下系統(tǒng)調用: pfnSYS_WRITE=IWrite; /printf和寫文件需要。 pfnSYS_EXIT=IExit; /退出時return后調用 pfnSYS_CREATE=ICreate; /創(chuàng)建文件 pfnSYS_OPEN=IOpen;/打開文件 pfnSYS_CLOSE=IClose; /關閉文件 pfnSYS_READ=IRead; / 讀文件 pfnSYS_FILESIZE=IFileSize; /返回文件大小 pfnSYS_EXEC=IExec; /加載

10、用戶程序 pfnSYS_WAIT=IWait;/等待子進程結束 pfnSYS_SEEK=ISeek; /移動文件指針 pfnSYS_REMOVE=IRemove; /刪除文件 pfnSYS_TELL=ITell; /返回文件指針位置 pfnSYS_HALT=IHalt; /關機要想完成以上系統(tǒng)調用,還要明白系統(tǒng)調用的機制,見后邊。參考文件有:src/lib/user/syscall.c 了解每個系統(tǒng)調用的形式。 src/lib/syscall-nr.h 了解每個系統(tǒng)調用號。實現方法:(1) 搭建框架用一個數組保存各函數名,數組下標就是系統(tǒng)調用號。在syscall_init()函數中初始化數組p

11、fn為NULL在syscall_handler()函數中依據系統(tǒng)調用號調用相函數。typedef void (*CALL_PROC)(struct intr_frame*);CALL_PROC pfnMAXCALL;voidsyscall_init (void) intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); int i; for(i=0;i<MAXCALL;i+) pfni=NULL;static voidsyscall_handler (struct intr_frame *f /

12、*UNUSED*/) if(!is_user_vaddr(f->esp) ExitStatus(-1); int No=*(int *)(f->esp); if(No>=MAXCALL|MAXCALL<0) printf("We don't have this System Call!n"); ExitStatus(-1); if(pfnNo=NULL) printf("this System Call %d not Implement!n",No); ExitStatus(-1); pfnNo(f);(2)每一個系統(tǒng)調用

13、的實現。完整代碼見附錄SYS_WRITE-void IWrite(struct intr_frame *f)printf 函數會調用這個系統(tǒng)調用向屏幕輸出,所以不實現這個系統(tǒng)調用,用戶程序將無法輸出任何字符。寫文件也要用這個系統(tǒng)調用。所以要使用pintos自帶的一個簡單的文件系統(tǒng)。首先從用戶棧中取出三個參數-fd,buffer,size如果 fd 是文件句柄,先要從進程打開文件表中找到該句柄對應的文件指針再調用pintos提供的file_write()函數向文件寫入數據。 打開文件表將在打開文件時建立,到SYS_OPEN系統(tǒng)調用實現時再講其具體實現。如果fd是標準輸出stdout句柄則調用pu

14、tbuf 函數向終端輸出。SYS_EXIT- void IExit(struct intr_frame *f); 用戶程序正常退出會調用這個系統(tǒng)調用。取出返回值,保存到進程控制塊的ret變量中。調用thread_exit()函數退出進程用戶程序非正常退出(如越界訪問等原因)需要另加一個函數來實現。void ExitStatus(int status) /非正常退出時使用 struct thread *cur=thread_current(); cur->ret=status; /保存返回值。 thread_exit();SYS_CREATE-創(chuàng)建文件 void ICreate(struc

15、t intr_frame *f) 取出僅有的一個參數文件名。調用filesys_create()函數。保存返回值。SYS_OPEN-打開文件void IOpen(struct intr_frame *f)取出文件名。調用filesys_open()函數打開文件。這里需要為每個進程維護一個打開文件表。打開文件后要為這個文件分配一個句柄號。在struct thread 結構中加入: int FileNum; /打開文件數 限制進程打開文件數 struct list file_list; /打開文件列表 int maxfd; /句柄分配使用每打開一個文件就讓maxfd加1,關閉文件可以不減小。關聯文

16、件句柄與文件指針的結構:(被鏈入file_list)struct file_node int fd; struct list_elem elem; struct file *f;有了以上準備,每打開一個文件都要新創(chuàng)建一個file_node結構,分配句柄,并把file_node加入file_list; 最后返回文件句柄就OK.SYS_CLOSE關閉文件 void IClose(struct intr_frame *f)一種是關閉一個文件。一種是進程退出時關閉所有文件。從用戶棧中獲取要關閉文件的句柄。在用戶打開文件列表中找到對應文件,以得到文件指針。調用file_close()函數關閉文件,釋放s

17、truct file_node。關閉所有文件自然是每一個都要關閉,釋放了。 Debug here 3 weeksSYS_READ讀文件IRead()從用戶棧中獲得fd buffer size三個參數如果fd是標準輸入設備,則調用input_getc()如果fd是文件句柄由fd 從進程打開文件表中得到文件指針調用file_read()函數從文件中讀數據。SYS_FILESIZE 獲取文件大小 IFileSize()從用戶棧中獲得fd由fd 從進程打開文件表中得到文件指針調用file_len gth得到文件大小SYS_EXEC - 加載用戶程序 IExec()用戶程序通過SYS_EXEC這個系統(tǒng)調

18、用創(chuàng)建子進程。在IExec()函數中,分配一個頁,復制一份用戶提供的用戶名。否則在后來分離參數時,加入0時出現核心線程寫入用戶內存空間的頁錯誤。還要注意線程同步問題。在IExec()中調用process_execute()函數創(chuàng)建子進程,但是從process_execute()得到了用戶進程pid后,用戶程序并沒用加載。所以要等待用戶進程被調度后調用了start_process()函數才能知道。 Start_process()函數真正加載用戶程序,可能會因為找不到程序文件或內存不足等原因導致加載失敗。 所以父進程調用process_execute()后不能立即返回,要在一個信號量上等待sema

19、_down(sema),直到start_process()函數中加載用戶程序成功后再semp_up(sema)激活父進程,激活父進程后應該立即掛起自己sema_down(sema),這里父進程獲取子進程狀態(tài)信息后,再出父進程sema_up()激活子進程。 如果父進程創(chuàng)建了一個優(yōu)先級比自己高的子進程,如果不這樣坐,start_process()函數每一次執(zhí)行sema_up(sema)后,父進程還是不會被調度,而子進程可以已經運行完畢,這樣父進程就得不到子進程的狀態(tài)了。在struct_thread結構中加入semaphore SemaWaitSuccess;可以在父進程的的這個信號量上等,也可是子

20、進程的SemaWaitSuccess上等。如果子進程創(chuàng)建成功則返回pid,失敗返回-1。SYS_WAIT等待函數 IWait()主線程創(chuàng)建子進程后,出于他與子進程優(yōu)先級一樣,所以,二者交替執(zhí)行,這樣主線程就有可能先結束,這導致了一開始的test失敗。起初可以通過創(chuàng)建子進程時提高子進程優(yōu)先級或者在process_wait()中加入while(true)這樣的死循環(huán)來解決。后期要通過信號量同步。這個系統(tǒng)調用的需求: 父進程創(chuàng)建子進程后可能要等子進程結束。Process_wait()要返回子進程的返回值。情況有如下:父進程調用process_wait()時子進程還未結束,此進父進程將被掛起,等子進程

21、結束后再喚醒父進程,父進程再取得返回值。父進程調用process_wait()時子進程已經結束,這就要求子進程結束后應該把返回值保存到父進程的進程控控制塊中。于是在struct thread要加入一個鏈表,struct list sons_ret;結構:struct ret_dataint pid;int ret;struct list_elem elem;這樣就能保存子進程的返回值了。在struct thread結構中加入 bool bWait; 表示進程本身有沒有被父進程等待。 在struct thread結構中加入bool SaveData; 如果子進程已經把返回值保存到父進程里了就設S

22、aveData為true; SaveData應該被初始化為false;在struct thread結構中加入struct thread *father;表示父線程。每創(chuàng)建一個子線程,都要在子線程中記錄父線程。信號量同步方法:在struct thread結構中加入semaphore SemaWait;這里選擇在父進程的SemaWait上等。這個等待會把父進程的struct thread 進程控制塊插入到SemaWait的list中去。要想同時等待多個進程則不可能把父進程插入到多個子進程中去。當然,這里的測試只能等一個子進程,所以在父進程和子進程上等都可以。父進程執(zhí)行process_wait(ch

23、ild_pid)后,可以由child_pid得到子進程struct thread 指針t。通過遍歷all_list比較pid實現.如果在all_list沒有發(fā)現子進程的進程控制塊或者發(fā)現t->SaveData=true|t->status=THREAD_DYING;表示子進程已經結束,直接從自己的sons_ret鏈表中找到子進程的返回值返回就OK.如果子進程還在運行,則執(zhí)行sema_down(t->father->SemaWait)把自己掛起,子進程執(zhí)行完畢后,發(fā)現在bWait=true,自己被等待了,再釋放父進程sema_up(SemaWait); 如果bWait=f

24、ale,則不用喚醒父進程。父進程被喚醒后,再從sons_ret鏈表中得到子進程的返回值。每個子進程只能等一次,第二次等同一個子進程只能返回-1.一個進程結束時,在process_exit()函數中,要釋放自己打開的所有文件,保存返回值到父進程,輸出退出信息,如果有父進程在等他就喚醒父進程,釋放子進程鏈表。SYS_SEEK -移動文件指針 ISeek()從用戶棧中取出文件句fd柄要移動的距離,把fd轉為文件指針,調用file_seek()函數移動文件指針即可。SYS_REMOVE 刪除文件 IRemove從用戶棧中取出要刪除文件的文件名。調用filesys_remove()刪除文件。SYS_TE

25、LL 返回文件指針當前位置 ITell()從用戶棧中取出文件句fd柄要移動的距離,把fd轉為文件指針,調用file_tell()函數得到指針位置。SYS_HALT 關機 IHALT調用shutdown_power_off()函數關機用戶程序導致頁錯誤時,會進入page_fault()函數,在exception.c中。 在page_fault()中加入 if(not_present|(is_kernel_vaddr(fault_addr)&&user) ExitStatus(-1);來處理頁錯誤。Task4 Denying Writes to Executables不能寫入可執(zhí)行

26、文件在start_process函數中加入 t->FileSelf=filesys_open(token);file_deny_write(t->FileSelf);其中FileSelf變量是要在struct thread結構中添加的。進程退出時就解除:在process_exit()中加入 if(cur->FileSelf!=NULL) /撤銷對自己人deny_write file_allow_write(cur->FileSelf); file_close (cur->FileSelf); 注意:所有系統(tǒng)調用的返回值都放到用戶的eax寄存器中。取出參數時要對用戶

27、棧指針作詳細的檢查,是否越界,越界則直接調用Exit_Status(-1)中止用戶進程。用戶程序加載過程:(1)核心線程通過調用process_execute(char *file_name);函數來創(chuàng)建用戶進程。 File_name為要加載的文件名。這個函數中還調用了thread_create()函數為用戶進程創(chuàng)建了一個線程。File_name 和一個叫start_process的函數 被傳遞給了thread_create(), thread_create()函數創(chuàng)建線程后就把線程放入ready_list()等待被調度;(2) 得到CPU后就開始start_process(void *fil

28、e_name)函數。這個函數做了以下幾件事兒:根據file_name把用戶程序從硬盤調入內存,還為其分配了虛擬內存。注意這里要完成task2,不然文件名不正確,就沒法打開文件。給用戶分配了??臻g3GB開始。向低字節(jié)增長。在這里要實現參數分離,并且把參數按規(guī)定放入用戶棧中。(3)通過內嵌匯編 asm volatile (.)調用了用戶程序中的main()函數。(4)main()函數從棧中取出傳給他的參數,執(zhí)行完畢后會調用系統(tǒng)調用exit(),Exit()函數又調用thread_exit()函數,thread_exit()函數又調用process_exit()函數,最后在thread_exit()

29、函數中把即將退出的函數的進程控制塊struct thread從all_list中remove掉,調用了進程調度器schedule()函數,調用下一下進程執(zhí)行。系統(tǒng)調用過程:在用戶程序使用一個系統(tǒng)調用,如printf();在必然會觸發(fā)一個30號中斷,正如src/lib/user/syscall.c文件中所述??梢妳祩€數不同,系統(tǒng)調用不同。 這個30號中斷調用之前,把系統(tǒng)調用號、用戶參數(0到3個不等)壓入棧中。然后開始執(zhí)行中斷程序,中斷程序又調用了syscall_handler(struct intr_frame *f)函數,其中f是一個指向了用戶程序當前運行信息的的指針,其中就有用戶棧指針e

30、sp,所以在我們添加的系統(tǒng)調用中,就可以根據這個指針取出系統(tǒng)調用號和各個參數。系統(tǒng)調用結束后,要把返回值入如f->eax中.注意: 用戶棧中的各個參數并不連續(xù)存放: 三個參數write(fd,buffer,size); int fd=*(esp+2); char *buffer=(char *)*(esp+6); unsigned size=*(esp+3); 兩個參數create(pFileName,size); bool ret=filesys_create(const char *)*(unsigned int *)f->esp+4),*(unsigned int *)f-&

31、gt;esp+5); 一個參數 exit(-1);cur->ret=*(int *)f->esp+1);附錄:Task2 參數傳遞代碼(紅色)Task3 系統(tǒng)調用(藍色)Task4 deny write (綠色)tid_tprocess_execute (const char *file_name) char *fn_copy; tid_t tid; /* Make a copy of FILE_NAME. Otherwise there's a race between the caller and load(). */ fn_copy = palloc_get_page

32、 (0); if (fn_copy = NULL) return TID_ERROR; strlcpy (fn_copy, file_name, PGSIZE); char *real_name, *save_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

33、= TID_ERROR) palloc_free_page (fn_copy); return tid;/* A thread function that loads a user process and starts it running. */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, &q

34、uot; ", &save_ptr); / get real file name, use it in load() /* Initialize interrupt frame and load executable. */ memset (&if_, 0, 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

35、, &if_.esp); struct thread *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

36、 *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; /because user stack increase to low addr. strlcpy(esp,token,strlen(token)+2); /copy param to user stack argn+=e

37、sp; 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; /set new stack top palloc_free_page (file_name); asm volatile ("movl %0, %esp; jmp intr_exit&q

38、uot; : : "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

39、 "filesys/filesys.h"#include "filesys/file.h"#include "devices/input.h"#include "process.h"#include <string.h>#include "devices/shutdown.h"#define MAXCALL 21#define MaxFiles 200#define stdin 1static void syscall_handler (struct intr_frame *);ty

40、pedef void (*CALL_PROC)(struct intr_frame*);CALL_PROC pfnMAXCALL;void IWrite(struct intr_frame*);void IExit(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 IF

41、ileSize(struct intr_frame *f);void IExec(struct intr_frame *f);void IWait(struct intr_frame *f);void ISeek(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 (v

42、oid) intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); int i; for(i=0;i<MAXCALL;i+) pfni=NULL; pfnSYS_WRITE=IWrite; pfnSYS_EXIT=IExit; pfnSYS_CREATE=ICreate; pfnSYS_OPEN=IOpen; pfnSYS_CLOSE=IClose; pfnSYS_READ=IRead; pfnSYS_FILESIZE=IFileSize; pfnSYS_EXEC=IExec; pfnSYS_W

43、AIT=IWait; pfnSYS_SEEK=ISeek; pfnSYS_REMOVE=IRemove; pfnSYS_TELL=ITell; pfnSYS_HALT=IHalt;static voidsyscall_handler (struct intr_frame *f /*UNUSED*/) if(!is_user_vaddr(f->esp) ExitStatus(-1); int No=*(int *)(f->esp); if(No>=MAXCALL|MAXCALL<0) printf("We don't have this System C

44、all!n"); ExitStatus(-1); if(pfnNo=NULL) printf("this System Call %d not Implement!n",No); ExitStatus(-1); pfnNo(f);void IWrite(struct intr_frame *f) /三個參數 int *esp=(int *)f->esp; if(!is_user_vaddr(esp+7) ExitStatus(-1); int fd=*(esp+2); /文件句柄 char *buffer=(char *)*(esp+6); /要輸出人緩沖

45、unsigned size=*(esp+3); /輸出內容大小。 if(fd=STDOUT_FILENO) /標準輸出設備 putbuf (buffer, size); f->eax=0; else /文件 struct thread *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);/寫文件 void IExit(struct intr_frame

46、*f) /一個參數 正常退出時使用 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 ExitStatus(int status) /非正常退出時使用 struct thread *cur=thread_current(); cur->ret=status; thread_exit();void ICreate(struct i

47、ntr_frame *f) /兩個參數 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 *)*(unsigned int *)f->esp+4),*(unsigned int *)f->esp+5); f->eax=ret;void IOpen(struct intr_frame *f)

48、 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=(struct file_node *)malloc(sizeof(struct file_node); fn->f=filesys_open(FileName); if

49、(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 *)f->esp)+2) ExitStat

50、us(-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)

51、, struct 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_u

溫馨提示

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

評論

0/150

提交評論