版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、實用標準文檔Pintos project2作者:西安電子科技大學王永剛QQ:357543420這個項目將使pintos可以加載并執(zhí)行用戶程序,并且為用戶程序提供系統(tǒng)調(diào)用。Project2需要完成的的任務(wù)有四個:Task1Process Termination Messages進程終止信息Task2 Argument Passing參數(shù)傳遞Task3 System Calls系統(tǒng)調(diào)用Task4 Denying Writes to Executables不能寫入可執(zhí)行文件Task1: Process Termination Messages進程終止信息要求:1. 在進程結(jié)束時輸出退出代碼 ( 就是
2、 main 函數(shù)的返回值,或者異常退出代碼。注意: 用戶進程結(jié)束時輸入退出代碼, 核心線程返回時不輸入。輸出格式被規(guī)定如下:printf (“%s: exit(%d)n”,.);實現(xiàn)方法:1. 既然要打印返回值,就得用一個變量保存返回值,于是在 struct thread 結(jié)構(gòu)中加入一個變量回保存返回值: int ret;文案大全實用標準文檔在 init_thread() 函數(shù)中初始化為 (0這里可以不用初始化) 。2. 在線程退出里要保存其返回值到 ret 中,這個將在系統(tǒng)調(diào)用里的 exit 函數(shù)中保存,這里先不考慮。在什么地方加入 printf() 呢?每個線程結(jié)束后, 都要調(diào)用 thre
3、ad_exit() 函數(shù),如果是加載了 用 戶 進 程 , 在thread_exit()函 數(shù) 中 還 會 調(diào) 用process_exit()函數(shù), 在 process_exit()函數(shù)中,如果是用戶進程,那么其頁表一定不為NULL,而核心進程頁表一定為NULL,即只有用戶進程退出時if(pd!=NULL) 就會成立,所以在大括號中加入 :printf (“ %s: exit(%d)n”,cur-name,cur-ret);其中cur=thread_current();即當前線程的struct thread指針。TASK1 OKTASK2Argument Passing參數(shù)傳遞要求:1. 分離
4、從命令行傳入的文件名和各個參數(shù)。2. 按照 C函數(shù)調(diào)用約定,把參數(shù)放入棧中。實現(xiàn)方法:文案大全實用標準文檔1. 分離參數(shù)的方法 : 用 string.h中的 strtok_r()函數(shù),在 string.c中有詳細的說明。2. 在 process_execute() 函數(shù)中,因為 thread_create() 需要一個線程名,此時應(yīng)該傳遞給它文件名 ( 不帶參數(shù) ) ??扇缦绿幚恚篶har *real_name, *save_ptr;real_name = strtok_r (file_name, , &save_ptr);tid = thread_create (real_name, PRI
5、_DEFAULT,start_process, fn_copy);( 3)在 start_process() 函數(shù)中,再次分離參數(shù),放入棧中。由于在 process_execute() 對 file_name 作了復(fù)制,文件名并未丟失,但是要注意,無論加載用戶程序成功還是失敗,都得釋放file_name所占用的一個頁的空間(Debug here 3 weeks)。 注意:傳給 Load()函數(shù)的參數(shù)也只能有文件名, 所以在 load() 函數(shù)前要分離出文件名:char *token=NULL, *save_ptr=NULL;token = strtok_r (file_name, , &sav
6、e_ptr);success = load (token, &if_.eip, &if_.esp);參數(shù)放置的一種方法:(1)找到用戶棧指針 :在 start_process()函數(shù)中有 structintr_frameif_;這樣一個結(jié)構(gòu),其中有一個成員if_.esp,這就是用戶棧指針,在load() 函數(shù)文案大全實用標準文檔中為其賦值,分配了??臻g。( 2)調(diào)用 strtok_r 分離出一個個參數(shù) ( 就是一個個字符串了 ) ,把每個字符串都復(fù)制到用戶棧中, 并把他在棧中的位置記錄到一個數(shù)組中,以備下一步使用。注意:棧是向下增長,而字符串是向上增長。char *esp=(char *)if
7、_.esp;char *arg256; /assume numbers 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 stackargn+=esp;(3)要加入一個雙字的對齊, 因為是 32 位的,所以就是四字節(jié)對齊。while
8、(int)esp%4make)/word alignesp-;/注意:棧是向下增長,所以這里是而不是+;(4) 要將第( 2)步保存下的指針逆序放入棧中。按照 C約定,先要放入一個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_.es
9、p=esp如下圖擺放。如果命令行是:/bin/ls l foo bar完整代碼見附錄!TASK 3 system call系統(tǒng)調(diào)用要求:(1)實現(xiàn)以下系統(tǒng)調(diào)用:pfnSYS_WRITE=IWrite;/printf和寫文件需要。pfnSYS_EXIT=IExit;/退出時 return后調(diào)用pfnSYS_CREATE=ICreate;/創(chuàng)建文件pfnSYS_OPEN=IOpen;/ 打開文件pfnSYS_CLOSE=IClose;/關(guān)閉文件pfnSYS_READ=IRead;/讀文件pfnSYS_FILESIZE=IFileSize; /返回文件大小文案大全實用標準文檔pfnSYS_EXEC=
10、IExec;/加載用戶程序pfnSYS_WAIT=IWait;/等待子進程結(jié)束pfnSYS_SEEK=ISeek;/移動文件指針pfnSYS_REMOVE=IRemove;/刪除文件pfnSYS_TELL=ITell;/返回文件指針位置pfnSYS_HALT=IHalt;/關(guān)機要想完成以上系統(tǒng)調(diào)用,還要明白系統(tǒng)調(diào)用的機制,見后邊。參考文件有: src/lib/user/syscall.c了解每個系統(tǒng)調(diào)用的形式。src/lib/syscall-nr.h了解每個系統(tǒng)調(diào)用號。實現(xiàn)方法:( 1)搭建框架用一個數(shù)組保存各函數(shù)名,數(shù)組下標就是系統(tǒng)調(diào)用號。在 syscall_init()函數(shù)中初始化數(shù)組 p
11、fn 為 NULL在 syscall_handler() 函數(shù)中依據(jù)系統(tǒng)調(diào)用號調(diào)用相函數(shù)。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;iesp)ExitStatus(-1);int No=*(int *)(f-esp);文案大全實用標準文檔if(No=MAXCALL|MAXCALLret=status;/保存
12、返回值。thread_exit();3SYS_CREATE創(chuàng)-建文件 void ICreate(struct intr_frame *f)取出僅有的一個參數(shù)文件名。調(diào)用 filesys_create()函數(shù)。保存返回值。4 SYS_OPEN-打開文件void IOpen(struct intr_frame *f)取出文件名。調(diào)用 filesys_open()函數(shù)打開文件。這里需要為每個進程維護一個打開文件表。打開文件后要為這個文件分配一個句柄號。在 struct thread結(jié)構(gòu)中加入:int FileNum;/打開文件數(shù)限制進程打開文件數(shù)struct list file_list; /打開文
13、件列表文案大全實用標準文檔int maxfd;/句柄分配使用每打開一個文件就讓maxfd 加 1,關(guān)閉文件可以不減小。關(guān)聯(lián)文件句柄與文件指針的結(jié)構(gòu): (被鏈入 file_list)struct file_nodeint fd;struct list_elem elem;struct file *f;有了以上準備,每打開一個文件都要新創(chuàng)建一個file_node結(jié)構(gòu),分配句柄,并把file_node加入 file_list;最后返回文件句柄就OK.5SYS_CLOSE關(guān)閉文件 void IClose(struct intr_frame *f)一種是關(guān)閉一個文件。一種是進程退出時關(guān)閉所有文件。從用戶
14、棧中獲取要關(guān)閉文件的句柄。在用戶打開文件列表中找到對應(yīng)文件,以得到文件指針。調(diào)用file_close()函數(shù)關(guān)閉文件,釋放struct file_node。關(guān)閉所有文件自然是每一個都要關(guān)閉,釋放了。 Debug here 3 weeks6 SYS_READ讀文件IRead()從用戶棧中獲得fd buffer size三個參數(shù)如果 fd 是標準輸入設(shè)備,則調(diào)用input_getc()如果 fd 是文件句柄由 fd 從進程打開文件表中得到文件指針調(diào)用 file_read() 函數(shù)從文件中讀數(shù)據(jù)。文案大全實用標準文檔7 SYS_FILESIZE 獲取文件大小IFileSize()從用戶棧中獲得fd由
15、 fd 從進程打開文件表中得到文件指針調(diào)用 file_len gth得到文件大小8 SYS_EXEC - 加載用戶程序IExec()用戶程序通過 SYS_EXEC這個系統(tǒng)調(diào)用創(chuàng)建子進程。在 IExec() 函數(shù)中,分配一個頁,復(fù)制一份用戶提供的用戶名。否則在后來分離參數(shù)時,加入 0 時出現(xiàn)核心線程寫入用戶內(nèi)存空間的頁錯誤。還要注意線程同步問題。在 IExec() 中調(diào)用 process_execute() 函數(shù)創(chuàng)建子進程,但是從process_execute() 得到了用戶進程 pid 后,用戶程序并沒用加載。所以要等待用戶進程被調(diào)度后調(diào)用了 start_process() 函數(shù)才能知道。 S
16、tart_process() 函數(shù)真正加載用戶程序, 可能會因為找不到程序文件或內(nèi)存不足等原因?qū)е录虞d失敗。 所以父進程調(diào)用 process_execute() 后不 能 立即 返回, 要 在一 個 信號 量 上等 待sema_down(sema),直到 start_process() 函數(shù)中加載用戶程序成功后再 semp_up(sema)激活父進程,激活父進程后應(yīng)該立即掛起自己sema_down(sema),這里父進程獲取子進程狀態(tài)信息后,再出父進程sema_up()激活子進程。 如果父進程創(chuàng)建了一個優(yōu)先級比自己高的子進程,如果不這樣坐,start_process()函數(shù)每一次執(zhí)行 sema
17、_up(sema)文案大全實用標準文檔后,父進程還是不會被調(diào)度,而子進程可以已經(jīng)運行完畢,這樣父進程就得不到子進程的狀態(tài)了。在 struct_thread 結(jié)構(gòu)中加入 semaphore SemaWaitSuccess;可以在父進程的的這個信號量上等,也可是子進程的SemaWaitSuccess上等。如果子進程創(chuàng)建成功則返回pid ,失敗返回 -1 。9 SYS_WAIT等待函數(shù)IWait()主線程創(chuàng)建子進程后,出于他與子進程優(yōu)先級一樣,所以,二者交替執(zhí)行,這樣主線程就有可能先結(jié)束,這導(dǎo)致了一開始的test失敗。起初可以通過創(chuàng)建子進程時提高子進程優(yōu)先級或者在 process_wait() 中加
18、入 while(true) 這樣的死循環(huán)來解決。后期要通過信號量同步。這個系統(tǒng)調(diào)用的需求:父進程創(chuàng)建子進程后可能要等子進程結(jié)束。Process_wait()要返回子進程的返回值。情況有如下:父進程調(diào)用 process_wait()時子進程還未結(jié)束,此進父進程將被掛起, 等子進程結(jié)束后再喚醒父進程,父進程再取得返回值。父進程調(diào)用process_wait()時子進程已經(jīng)結(jié)束 , 這就要求子進程結(jié)束后應(yīng)該把返回值保存到父進程的進程控控制塊中。文案大全實用標準文檔于是在 struct thread要加入一個鏈表, struct list sons_ret;結(jié)構(gòu):struct ret_dataint p
19、id;int ret;struct list_elem elem;這樣就能保存子進程的返回值了。在 struct thread結(jié)構(gòu)中加入 bool bWait;表示進程本身有沒有被父進程等待。在 struct thread 結(jié)構(gòu)中加入 bool SaveData; 如果子進程已經(jīng)把返回值保存到父進程里了就設(shè) SaveData 為 true; SaveData 應(yīng)該被初始化為 false;在 struct thread 結(jié)構(gòu)中加入 struct thread *father; 表示父線程。每創(chuàng)建一個子線程,都要在子線程中記錄父線程。信號量同步方法:在 struct thread 結(jié)構(gòu)中加入 se
20、maphore SemaWait;這里選擇在父進程的 SemaWait上等。這個等待會把父進程的 struct thread 進程控制塊插入到 SemaWait的 list 中去。要想同時等待多個進程則不可能把父進程插入到多個子進程中去。 當然,這里的測試只能等一個子進程,所以在父進程和子進程上等都可以。父進程執(zhí)行 process_wait(child_pid)后,可以由 child_pid得到子進程 struct thread指針 t 。通過遍歷 all_list比較 pid 實現(xiàn) .文案大全實用標準文檔如 果 在all_list沒 有 發(fā) 現(xiàn) 子 進 程 的 進 程 控 制 塊 或 者 發(fā)
21、 現(xiàn)t-SaveData=true|t-status=THREAD_DYING; 表示子進程已經(jīng)結(jié)束,直接從自己的 sons_ret 鏈表中找到子進程的返回值返回就 OK. 如果子進程還在運行,則執(zhí)行 sema_down(t-father-SemaWait) 把自己掛起,子進程執(zhí)行完畢后, 發(fā)現(xiàn)在 bWait=true, 自己被等待了,再釋放父進程 sema_up(SemaWait); 如果 bWait=fale, 則不用喚醒父進程。父進程被喚醒后,再從sons_ret 鏈表中得到子進程的返回值。每個子進程只能等一次,第二次等同一個子進程只能返回-1.一個進程結(jié)束時,在 process_exi
22、t() 函數(shù)中,要釋放自己打開的所有文件,保存返回值到父進程,輸出退出信息,如果有父進程在等他就喚醒父進程,釋放子進程鏈表。10 SYS_SEEK -移動文件指針I(yè)Seek()從用戶棧中取出文件句 fd 柄要移動的距離,把 fd 轉(zhuǎn)為文件指針,調(diào)用 file_seek()函數(shù)移動文件指針即可。11 SYS_REMOVE刪除文件IRemove從用戶棧中取出要刪除文件的文件名。調(diào)用 filesys_remove()刪除文件。文案大全實用標準文檔12 SYS_TELL返回文件指針當前位置ITell()從用戶棧中取出文件句 fd 柄要移動的距離,把 fd 轉(zhuǎn)為文件指針,調(diào)用 file_tell()函數(shù)
23、得到指針位置。13 SYS_HALT 關(guān)機IHALT調(diào)用 shutdown_power_off()函數(shù)關(guān)機用戶程序?qū)е马撳e誤時, 會進入 page_fault() 函數(shù),在 exception.c 中。 在 page_fault() 中加入if(not_present|(is_kernel_vaddr(fault_addr)&user)ExitStatus(-1);來處理頁錯誤。Task4 Denying Writes to Executables不能寫入可執(zhí)行文件在 start_process 函數(shù)中加入t-FileSelf=filesys_open(token);file_deny_wri
24、te(t-FileSelf);其中 FileSelf變量是要在struct thread結(jié)構(gòu)中添加的。進程退出時就解除:在 process_exit() 中加入if(cur-FileSelf!=NULL) /撤銷對自己人deny_writefile_allow_write(cur-FileSelf);file_close (cur-FileSelf);注意:所有系統(tǒng)調(diào)用的返回值都放到用戶的eax 寄存器中。取出參數(shù)時要對用戶棧指針作詳細的檢查,是否越界,越界則直接調(diào)文案大全實用標準文檔用 Exit_Status(-1) 中止用戶進程。用戶程序加載過程:(1) 核心線程通過調(diào)用process_e
25、xecute(char *file_name);函數(shù)來創(chuàng)建用戶進程。File_name為要加載的文件名。這個函數(shù)中還調(diào)用了thread_create()函數(shù)為用戶進程創(chuàng)建了一個線程。 File_name 和一個叫 start_process的函數(shù)被傳遞給了 thread_create(), thread_create()函數(shù)創(chuàng)建線程后就把線程放入 ready_list()等待被調(diào)度 ;(2)得到 CPU后就開始 start_process(void *file_name)函數(shù)。這個函數(shù)做了以下幾件事兒:1 根據(jù)file_name把用戶程序從硬盤調(diào)入內(nèi)存,還為其分配了虛擬內(nèi)存。 注意這里要完成t
26、ask2 ,不然文件名不正確, 就沒法打開文件。2 給用戶分配了??臻g3GB開始。向低字節(jié)增長。在這里要實現(xiàn)參數(shù)分離,并且把參數(shù)按規(guī)定放入用戶棧中。文案大全實用標準文檔(3) 通過內(nèi)嵌匯編asm volatile (.) 調(diào)用了用戶程序中的 main() 函數(shù)。(4 )main() 函數(shù)從棧中取出傳給他的參數(shù),執(zhí)行完畢后會調(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ù)的進程控制塊structthread 從 all_list中 remov
27、e 掉,調(diào)用了進程調(diào)度器schedule() 函數(shù),調(diào)用下一下進程執(zhí)行。系統(tǒng)調(diào)用過程:在用戶程序使用一個系統(tǒng)調(diào)用, 如 printf();在必然會觸發(fā)一個30號中斷,正如src/lib/user/syscall.c文件中所述。可見參數(shù)個數(shù)不同,系統(tǒng)調(diào)用不同。 這個 30 號中斷調(diào)用之前,把系統(tǒng)調(diào)用號、用戶參數(shù)( 0 到 3 個不等)壓入棧中。然后開始執(zhí)行中斷程序,中斷程序又調(diào)用了 syscall_handler(struct intr_frame *f)函數(shù),其中 f是一個指向了用戶程序當前運行信息的的指針,其中就有用戶棧指針esp, 所以在我們添加的系統(tǒng)調(diào)用中, 就可以根據(jù)這個指針取出系統(tǒng)調(diào)
28、用號和各個參數(shù)。系統(tǒng)調(diào)用結(jié)束后,要把返回值入如f-eax 中.注意:用戶棧中的各個參數(shù)并不連續(xù)存放:三個參數(shù)write(fd,buffer,size);int fd=*(esp+2);文案大全實用標準文檔char *buffer=(char *)*(esp+6);unsigned size=*(esp+3);兩個參數(shù)create(pFileName,size);bool ret=filesys_create(const char *)*(unsigned int*)f-esp+4),*(unsigned int *)f-esp+5);一個參數(shù)exit(-1);cur-ret=*(int *)f
29、-esp+1);附錄:Task2 參數(shù)傳遞代碼 ( 紅色 )Task3 系統(tǒng)調(diào)用(藍色)Task4 deny 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_cop
30、y, 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 = TID_ERROR)palloc_free_page (fn_copy);return tid;/* A thread function that lo
31、ads 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, , &save_ptr); / get real file name, use it in load()/* Initialize interrupt fr
32、ame 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, &if_.esp);struct thread *t=thread_current();if (!success)palloc_free_page (file_name);t-tid=-1;sema_up(&
33、t-SemaWaitSuccess);ExitStatus(-1);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 256int i,n=0;for (; token != NULL;token = strtok_r (NULL, , &save_ptr)/copy theargument to user stackesp-=
34、strlen(token)+1;/because user stackincrease to low addr.strlcpy(esp,token,strlen(token)+2);/copyparam to user stackargn+=esp;文案大全實用標準文檔while(int)esp%4make)/word alignesp-;int *p=esp-4;*p-=0;/first 0for(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_
35、.esp=esp;/set new stack toppalloc_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.
36、h#include 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_fram
37、e*);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 IFileSize(struct intr_frame *f);文案大全實用標準文檔void IExec(struct intr_frame *f);void IWait(struct in
38、tr_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 (void)intr_register_int (0x30, 3, INTR_ON, syscall_handler, syscall); int i;for(i=0;i
39、esp)ExitStatus(-1);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)/標準輸出設(shè)備putbuf (buffer, size);f-eax=0;else/文件struct thread *cur=thread_current();stru
40、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) /一個參數(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
41、xitStatus(int status)/非正常退出時使用struct thread *cur=thread_current();cur-ret=status;thread_exit();void ICreate(struct intr_frame *f) /兩個參數(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);boolret=filesys_create(constchar*)*(unsignedint*)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. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度企業(yè)合規(guī)管理體系建設(shè)合同范本及實施指南3篇
- 2025年度個人貨車租賃合同保險條款說明3篇
- 2025年度旅游行業(yè)知識產(chǎn)權(quán)顧問合同4篇
- 2025年女方放棄撫養(yǎng)費及子女監(jiān)護權(quán)離婚協(xié)議書子女成長支持協(xié)議
- 2025年度高新技術(shù)企業(yè)股份無償贈與合作協(xié)議
- 二零二五年度石材行業(yè)環(huán)保政策咨詢合同
- 二零二五年度專業(yè)護理機構(gòu)護工勞動合同
- 二零二五年度銀行承兌匯票擔保業(yè)務(wù)風險管理協(xié)議
- 二零二五版房建木工勞務(wù)合同合同解除與終止流程范本3篇
- 2025年度農(nóng)產(chǎn)品電商銷售合同履約保障與風險控制
- 《色彩基礎(chǔ)》課程標準
- 人力資源 -人效評估指導(dǎo)手冊
- 大疆80分鐘在線測評題
- 2023年成都市青白江區(qū)村(社區(qū))“兩委”后備人才考試真題
- 2024中考復(fù)習必背初中英語單詞詞匯表(蘇教譯林版)
- 《現(xiàn)代根管治療術(shù)》課件
- 肩袖損傷的護理查房課件
- 2023屆北京市順義區(qū)高三二模數(shù)學試卷
- 公司差旅費報銷單
- 2021年上海市楊浦區(qū)初三一模語文試卷及參考答案(精校word打印版)
- 八年級上冊英語完形填空、閱讀理解100題含參考答案
評論
0/150
提交評論