Linu下的系統(tǒng)調用_第1頁
Linu下的系統(tǒng)調用_第2頁
Linu下的系統(tǒng)調用_第3頁
Linu下的系統(tǒng)調用_第4頁
Linu下的系統(tǒng)調用_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、Linux 下的系統(tǒng)調用1 什么是系統(tǒng)調用系統(tǒng)調用,顧名思義,說的是操作系統(tǒng)提供給用戶程序調用的一組“特殊” 接口。用戶程序可以通過這組“特殊”接口來獲得操作系統(tǒng)內核提供的服務,比 如用戶可以通過文件系統(tǒng)相關的調用請求系統(tǒng)打開文件、關閉文件或讀寫文件, 可以通過時鐘相關的系統(tǒng)調用獲得系統(tǒng)時間或設置定時器等。從邏輯上來說,系統(tǒng)調用可被看成是一個內核與用戶空間程序交互的接口 它好比一個中間人,把用戶進程的請求傳達給內核,待內核把請求處理完畢后 再將處理結果送回給用戶空間。系統(tǒng)服務之所以需要通過系統(tǒng)調用來提供給用戶空間的根本原因是為了對 系統(tǒng)進行“保護”,因為我們知道 Linux 的運行空間分為內核

2、空間與用戶空間, 它們各自運行在不同的級別中,邏輯上相互隔離。所以用戶進程在通常情況下不 允許訪問內核數(shù)據(jù),也無法使用內核函數(shù),它們只能在用戶空間操作用戶數(shù)據(jù), 調用用戶空間函數(shù)。比如我們熟悉的“hello world”程序(執(zhí)行時)就是標準的用 戶空間進程,它使用的打印函數(shù)printf就屬于用戶空間函數(shù),打印的字符“ hello word”字符串也屬于用戶空間數(shù)據(jù)。但是很多情況下,用戶進程需要獲得系統(tǒng)服務(調用系統(tǒng)程序),這時就必 須利用系統(tǒng)提供給用戶的“特殊接口”系統(tǒng)調用了,它的特殊性主要在于規(guī) 定了用戶進程進入內核的具體位置;換句話說,用戶訪問內核的路徑是事先規(guī)定 好的,只能從規(guī)定位置進

3、入內核,而不準許肆意跳入內核。有了這樣的陷入內核 的統(tǒng)一訪問路徑限制才能保證內核安全無虞。我們可以形象地描述這種機制:作 為一個游客,你可以買票要求進入野生動物園,但你必須老老實實地坐在觀光車 上,按照規(guī)定的路線觀光游覽。當然,不準下車,因為那樣太危險,不是讓你丟 掉小命,就是讓你嚇壞了野生動物。2 Linux的系統(tǒng)調用對于現(xiàn)代操作系統(tǒng),系統(tǒng)調用是一種內核與用戶空間通訊的普遍手段, Linux系統(tǒng)也不例外。但是Linux系統(tǒng)的系統(tǒng)調用相比很多Unix和windows等 系統(tǒng)具有一些獨特之處,無處不體現(xiàn)出Linux的設計精髓一一簡潔和高效。Linux系統(tǒng)調用很多地方繼承了 Unix的系統(tǒng)調用(但

4、不是全部),但Linux 相比傳統(tǒng)Unix的系統(tǒng)調用做了很多揚棄,它省去了許多Unix系統(tǒng)冗余的系統(tǒng)調 用,僅僅保留了最基本和最有用的系統(tǒng)調用,所以Linux全部系統(tǒng)調用只有250 個左右(而有些操作系統(tǒng)系統(tǒng)調用多達 1000個以上)。這些系統(tǒng)調用按照功能邏輯大致可分為“進程控制”、“文件系統(tǒng)控制”、“系統(tǒng) 控制” “存儲管理” “網(wǎng)絡管理” “socket控制” “用戶管理” “進程間通信” 等幾類,詳細情況可參閱文章系統(tǒng)調用列表如果你想詳細看看系統(tǒng)調用的說明,可以使用man 2 syscalls命令查看,或干 脆到 內核源碼目錄/include/asm-i386/unistd.h源文件中找

5、到它們的源本。熟練了解和掌握上面這些系統(tǒng)調用是對系統(tǒng)程序員的必備要求,但對于一個開 發(fā)內核的人員或內核開發(fā)者來11說,死記硬背下這些調用還遠遠不夠。如果你 僅僅知道存在的調用而不知道為什么它們會存在,或只知道如何使用調用而不知 道這些調用在系統(tǒng)中的主要用途,那么你離駕馭系統(tǒng)還有不小距離。要彌補這個鴻溝,第一,你必須明白系統(tǒng)調用在內核里的主要用途。雖然上面 給出了數(shù)種分類,不過,總的概括來講,系統(tǒng)調用在系統(tǒng)中的主要用途無非以下 幾類:控制硬件一一系統(tǒng)調用往往作為硬件資源和用戶空間的抽象接口,比 如讀寫文件時用到的 write/read 調用。設置系統(tǒng)狀態(tài)或讀取內核數(shù)據(jù)因為系統(tǒng)調用是用戶空間和內核

6、的 唯一通訊手段22,所以用戶設置系統(tǒng)狀態(tài),比如開/關某項內核服務(設 置某個內核變量) ,或讀取內核數(shù)據(jù)都必須通過系統(tǒng)調用。比如 getpgid、getpriority、setpriority、sethostname進程管理一系統(tǒng)調用接口是用來保證系統(tǒng)中進程能以多任務在虛 擬內存環(huán)境下得以運行。比如 fork、clone、execve、exit 等第二,什么服務應該存在于內核;或者說什么功能應該實現(xiàn)在內核而不是 在用戶空間。這個問題并沒有明確的答案,有些服務你可以選擇在內核完成,也 可以在用戶空間完成。選擇在內核完成通常基于以下考慮:服務必須獲得內核數(shù)據(jù),比如一些服務必須獲得中斷或系統(tǒng)時間等

7、內 核數(shù)據(jù)。從安全角度考慮,在內核中提供的服務相比用戶空間提供的毫無疑問 更安全,很難被非法訪問到。從效率考慮,在內核實現(xiàn)服務避免了和用戶空間來回傳遞數(shù)據(jù)以及保護現(xiàn)場等步驟,因此效率往往要比在用戶空間實現(xiàn)高許多。比如,httpd 等服務。如果內核和用戶空間都需要使用該服務,那么最好實現(xiàn)在內核空間, 比如隨機數(shù)產生。理解上述道理對掌握系統(tǒng)調用的本質意義很大,希望網(wǎng)友們能從使用中多總 結,多思考。3系統(tǒng)調用、用戶編程接口 API).系統(tǒng)命令和內核函數(shù)的關系系統(tǒng)調用并非直接和程序員或系統(tǒng)管理員打交道,它僅僅是一個通過軟中斷 機制(我們后面講述)向內核提交請求,獲取內核服務的接口。而在實際使用中 程序

8、員調用的多是用戶編程接口一一API,而管理員使用的則多是系統(tǒng)命令。用戶編程接口其實是一個函數(shù)定義,說明了如何獲得一個給定的服務,比如read()、malloc()、free ()、abs()等。它有可能和系統(tǒng)調用形式上一致,比如read() 接口就和 read 系統(tǒng)調用對應,但這種對應并非一一對應,往往會出現(xiàn)幾種不同 的API內部用到同一個系統(tǒng)調用,比如malloc()、free ()內部利用brk()系統(tǒng)調 用來擴大或縮小進程的堆;或一個 API 利用了好幾個系統(tǒng)調用組合完成服務。 更有些 API 甚至不需要任何系統(tǒng)調用因為它并不是必需要使用內核服務, 如計算整數(shù)絕對值的abs ()接口。另

9、外要補充的是Linux的用戶編程接口遵循了在Unix世界中最流行的應用 編程界面標準POSIX標準,這套標準定義了一系列API。在Linux中(Unix 也如此),這些API主要是通過C庫(libc)實現(xiàn)的,它除了定義的一些標準的C 函數(shù)外,一個很重要的任務就是提供了一套封裝例程(wrapper routine)將系統(tǒng) 調用在用戶空間包裝后供用戶編程使用。不過封裝并非必須的,如果你愿意直接調用,Linux內核也提供了一個syscall() 函數(shù)來實現(xiàn)調用,我們看個例子來對比一下通過C庫調用和直接調用的區(qū)別。#include #include #include #include int main

10、(void) long ID1, ID2; TOC o 1-5 h z /*/* 直接系統(tǒng)調用*/* SYS_getpid (func no. is 20) */*/ID1 = syscall(SYS_getpid);printf (syscall(SYS_getpid)=%ldn, ID1); /*/*使用libc封裝的系統(tǒng)調用*/* SYS_getpid (Func No. is 20) */*/ID2 = getpid();printf (getpid()=%ldn, ID2); return(0);系統(tǒng)命令相對編程接口更高了一層,它是內部引用API的可執(zhí)行程序,比如 我們常用的系統(tǒng)命令

11、Is、hostname等。Linux的系統(tǒng)命令格式遵循系統(tǒng)V的傳統(tǒng), 多數(shù)放在/bin和/sbin下(相關內容可看看shell等章節(jié))。有興趣的話,可以通過strace ls或strace hostname命令查看一下它們用到的 系統(tǒng)調用,你會發(fā)現(xiàn)諸如open、brk、fstat、ioctl等系統(tǒng)調用被用在系統(tǒng)命令中。下一個需要解釋一下的問題是內核函數(shù)和系統(tǒng)調用的關系。大家不要把內核 函數(shù)想像的過于復雜,其實它們和普通函數(shù)很像,只不過在內核實現(xiàn),因此要滿 足一些內核編程的要求33。系統(tǒng)調用是一層用戶進入內核的接口,它本身并非 內核函數(shù),進入內核后,不同的系統(tǒng)調用會找到對應到各自的內核函數(shù)換個

12、專業(yè)說法就叫:系統(tǒng)調用服務例程。實際上針對請求提供服務的是內核函數(shù)而非 調用接口。比如系統(tǒng)調用 getpid 實際上就是調用內核函數(shù) sys_getpid。 asmlinkage long sys_getpid(void)return current-tpid;Linux 系統(tǒng)中存在許多內核函數(shù),有些是內核文件中自己使用的,有些則是 可以export出來供內核其他部分共同使用的,具體情況自己決定。內核公開的內核函數(shù) export出來的 可以使用命令ksyms或cat /proc/ksyms來查看。另外,網(wǎng)上還有一本歸納分類內核函數(shù)的書叫作The Linux Kernel API Book,有興

13、趣的讀者可以去看看??偠灾?,從用戶角度向內核看,依次是系統(tǒng)命令、編程接口、系統(tǒng)調用和 內核函數(shù)。在講述了系統(tǒng)調用實現(xiàn)后,我們會回過頭來看看整個執(zhí)行路徑。4 系統(tǒng)調用的實現(xiàn)Linux 中實現(xiàn)系統(tǒng)調用利用了 0 x86 體系結構中的軟件中斷44。軟件中斷和 我們常說的中斷(硬件中斷)不同之處在于它是通過軟件指令觸發(fā)而并非外 設引發(fā)的中斷,也就是說,又是編程人員開發(fā)出的一種異常,具體的講就是調用 int $0 x80匚編指令,這條匯編指令將產生向量為128的編程異常。之所以系統(tǒng)調用需要借助異常來實現(xiàn),是因為當用戶態(tài)的進程調用一個系統(tǒng) 調用時,CPU便被切換到內核態(tài)執(zhí)行內核函數(shù)55,而我們在i386

14、體系結構部分 已經(jīng)講述過了進入內核進入高特權級別必須經(jīng)過系統(tǒng)的門機制,這里的 異常實際上就是通過系統(tǒng)門陷入內核(除了 int 0 x80外用戶空間還可以通過int3 向量3、into向量4、bound向量5等異常指令進入內核,而其他異 常無法被用戶空間程序利用,都是由系統(tǒng)使用的)。我們更詳細地解釋一下這個過程。int $0 x80指令的目的是產生一個編號為 128的編程異常,這個編程異常對應的是中斷描述符表IDT中的第128項也 就是對應的系統(tǒng)門描述符。門描述符中含有一個預設的內核空間地址,它指向了 系統(tǒng)調用處理程序:system_call()(別和系統(tǒng)調用服務程序混淆,這個程序在entry.

15、S 文件中用匯編語言編寫)。很顯然,所有的系統(tǒng)調用都會統(tǒng)一地轉到這個地址,但 Linux 一共有 2、3 百個系統(tǒng)調用都從這里進入內核后又該如何派發(fā)到它們到各自的服務程序去 呢?別發(fā)昏,解決這個問題的方法非常簡單:首先Linux為每個系統(tǒng)調用都進行 了編號(0NR_syscall),同時在內核中保存了一張系統(tǒng)調用表,該表中保存了 系統(tǒng)調用編號和其對應的服務例程,因此在系統(tǒng)調入通過系統(tǒng)門陷入內核前,需 要把系統(tǒng)調用號一并傳入內核,在 x86 上,這個傳遞動作是通過在執(zhí)行 int0 x80 前把調用號裝入eax寄存器實現(xiàn)的。這樣系統(tǒng)調用處理程序一旦運行,就可以從 eax 中得到數(shù)據(jù),然后再去系統(tǒng)調

16、用表中尋找相應服務例程了。除了需要傳遞系統(tǒng)調用號以外,許多系統(tǒng)調用還需要傳遞一些參數(shù)到內核, 比如 sys_write(unsigned int fd, const char * buf, size_t count)調用就需要傳遞文件 描述符fd、要寫入的內容buf、以及寫入字節(jié)數(shù)count等幾個內容到內核。碰到 這種情況,Linux會有6個寄存器可被用來傳遞這些參數(shù):eax (存放系統(tǒng)調用號)、 ebx、ecx、edx、esi及edi來存放這些額外的參數(shù)(以字母遞增的順序)。具體做 法是在 system_call( )中使用 SAVE_ALL 宏把這些寄存器的值保存在內核態(tài)堆棧 中。有始便有

17、終,當服務例程結束時,system_call()從eax獲得系統(tǒng)調用的返 回值,并把這個返回值存放在曾保存用戶態(tài)eax寄存器棧單元的那個位置上。 然后跳轉到ret_from_sys_call(),終止系統(tǒng)調用處理程序的執(zhí)行。當進程恢復它在用戶態(tài)的執(zhí)行前,RESTORE_ALL宏會恢復用戶進入內核前 被保留到堆棧中的寄存器值。其中 eax 返回時會帶回系統(tǒng)調用的返回碼。(負數(shù) 說明調用錯誤,0 或正數(shù)說明正常完成)我們可以通過分析一下getpid系統(tǒng)調用的真是過程來將上述概念具體化,分 析 getpid 系統(tǒng)調用的一個辦法是查看 entry.s 中的代碼細節(jié),逐步跟蹤源碼來分 析運行過程,另外就

18、是可借助一些內核調試工具,動態(tài)跟蹤運行路徑。假設我們的程序源文件名為getpid.c,內容是:#include #include #include #include int main(void) long ID;ID = getpid();printf (getpid()=%ldn, ID);return(0);將其編譯成名為getpid的執(zhí)行文件“gcc -o getpid 提示符下,執(zhí)行bt命令觀察堆棧,發(fā)現(xiàn)調用的嵌套路徑,可以看到在sys_getpid 是在內核函數(shù)system_call中被嵌套調用的。在KDB提示符下,執(zhí)行rd命令查看寄存器中的數(shù)值,可以看到eax中存放的getpid

19、調用號0 x00000014(=20).在KDB提示符下,執(zhí)行ssb (或ss)命令跟蹤內核代碼執(zhí)行路徑,可以發(fā)現(xiàn)sys_getpid 執(zhí)行后,會返回system_call函數(shù),然后接者轉入ret_from_sys_call例程。(再往后還有 些和調度有關其他例程,我們這里不說了它們了。)結合用戶空間的執(zhí)行路徑,該程序大致可歸結為以下幾個步驟:1該程序調用libc庫的封裝函數(shù)getpid。該封裝函數(shù)將系統(tǒng)調用號_NR_getpid (第20個) 壓入EAX寄存器,2 調用軟中斷 int 0 x80 進入內核。(以下進入內核態(tài))3在內核中首先執(zhí)行system_call,接著執(zhí)行根據(jù)系統(tǒng)調用號在調

20、用表中查找到的對應的系 統(tǒng)調用服務例程sys_getpid。4.執(zhí)行sys_getpid服務例程。5執(zhí)行完畢后,轉入 ret_from_sys_call 例程,系統(tǒng)調用中返回。內核調試是一個很有趣的話題,方法多種多樣,我個人認為比較好用的 是UML(user mode linux+gdb)和 KDB 這兩個工具。尤其KDB對于調試小 規(guī)模內核模塊或查看內核運行路徑很有效,對于它的使用方法可以看看Linux 內核調試器內幕這篇文章。5.系統(tǒng)調用思考系統(tǒng)調用的內在過程并不復雜,我們不再多說了,下面這節(jié)我們主要就系統(tǒng) 調用所涉及的一些重要問題作一些討論和分析,希望這樣能更有助于了解系統(tǒng)調 用的精髓。

21、51. 調用上下文分析系統(tǒng)調用雖說是要進入內核執(zhí)行,但它并非一個純粹意義上的內核例程。首 先它是代表用戶進程的,這點決定了雖然它會陷入內核執(zhí)行,但是上下文仍然是 處于進程上下文中,因此可以訪問進程的許多信息(比如 current 結構當前 進程的控制結構) ,而且可以被其他進程搶占(在從系統(tǒng)調用返回時,由 system_call 函數(shù)判斷是否該再調度),可以休眠,還可接收信號66等等。所有這些特點都涉及到了進程調度的問題,我們這里不做深究,只要大家明 白系統(tǒng)調用完成后,再回到或者說把控制權交回到發(fā)起調用的用戶進程前,內核 會有一次調度。如果發(fā)現(xiàn)有優(yōu)先級別更高的進程或當前進程的時間片用完,那么

22、就會選擇高優(yōu)先級的進程或重新選擇進程運行。除了再調度需要考慮外,再就是 內核需要檢查是否有掛起的信號,如果發(fā)現(xiàn)當前進程有掛起的信號,那么還需要 先返回用戶空間處理信號處理例程(處于用戶空間),然后再回到內核,重新返 回用戶空間,有些麻煩但這個反復過程是必須的。52 調用性能問題系統(tǒng)調用需要從用戶空間陷入內核空間,處理完后,又需要返回用戶空間。 其中除了系統(tǒng)調用服務例程的實際耗時外,陷入 /返回過程和系統(tǒng)調用處理程序 (查系統(tǒng)調用表、存儲/恢復用戶現(xiàn)場)也需要花費一些時間,這些時間加起來 就是一個系統(tǒng)調用的響應速度。系統(tǒng)調用不比別的用戶程序,它對性能要求很苛 刻,因為它需要陷入內核執(zhí)行,所以和其

23、他內核程序一樣要求代碼簡潔、執(zhí)行迅 速。幸好Linux具有令人難以置信的上下文切換速度,使得其進出內核都被優(yōu)化 得簡潔高效;同時所有Linux系統(tǒng)調用處理程序和每個系統(tǒng)調用本身也都非常簡 潔。絕大多數(shù)情況下,Linux系統(tǒng)調用的性能是可以接受的,但是對于一些對性 能要求非常高的應用來說,它們雖然希望利用系統(tǒng)調用的服務,但卻希望加快響 應速度,避免陷入/返回和系統(tǒng)調用處理程序帶來的花銷,因此采用由內核直接 調用系統(tǒng)調用服務例程,最好的例子就HTTPD它為了避免上述開銷,從內 核調用socket等系統(tǒng)調用服務例程。53什么時候添加系統(tǒng)調用系統(tǒng)調用是用戶空間和內核空間交互的唯一手段,但是這并不是說要

24、完成交 互功能就非要添加新系統(tǒng)調用不可。添加系統(tǒng)調用需要修改內核源代碼、重新編 譯內核,因此如果想靈活地和內核交互信息,最好使用以下幾種方法:編寫字符驅動程序利用字符驅動程序可以完成和內核交互數(shù)據(jù)的功能。它最大的好處在于可以 模塊式加載,這樣一來就避免了編譯內核等手續(xù),而且調用接口固定,容易 操作。使用 proc 文件系統(tǒng)利用proc文件系統(tǒng)修訂系統(tǒng)狀態(tài)是一種很常見的手段,比如通過修改proc 文件系統(tǒng)下的系統(tǒng)參數(shù)配置文件(/proc/sys),我們可以直接在運行時動態(tài)更 改內核參數(shù);再如,通過下面這條指令:echo 1 /proc/sys/net/ip_v4/ip_forward 開啟內核中

25、控制IP轉發(fā)的開關。類似的,還有許多內核選項可以直接通過 proc 文件系統(tǒng)進行查詢和調整。使用虛擬文件系統(tǒng)有些內核開發(fā)者認為利用ioctl ()系統(tǒng)調用(字符設備驅動接口)往往會使 得系統(tǒng)調用意義不明確,而且難以控制。而將信息放入到proc文件系統(tǒng)中會使 信息組織混亂,因此也不贊成過多使用。他們建議實現(xiàn)一種孤立的虛擬文件系統(tǒng) 來代替ioctl()和/proc,因為文件系統(tǒng)接口清楚,而且便于用戶空間訪問,同時, 利用虛擬文件系統(tǒng)使得利用腳本執(zhí)行系統(tǒng)管理任務更加方便、有效。6試驗部分61 試驗概述 本章的試驗,我們將編寫一個搜集內核中系統(tǒng)調用發(fā)生序列信息的內核服 務,并利用一個新的系統(tǒng)調用為用戶

26、程序取回這些信息。這個試驗不但能教會大家如何為內核添加新系統(tǒng)調用,而且能教大家學會 用戶程序如何使用系統(tǒng)調用獲取內核服務。更進一步,大家可以通過觀察系統(tǒng)調 用序列和發(fā)生頻率更深入地理解系統(tǒng)調用和系統(tǒng)運行的關系。當然,這里除了系 統(tǒng)調用的知識外,還會涉及到一些有關內核編程,比如等待隊列、內核模塊等知 識,這些部分請大家查看相關資料。我們的新系統(tǒng)調用為audit (在2.4.18內核中系統(tǒng)調用號是223,置于調用表 最末尾),該調用對應的具體實現(xiàn)是內核函數(shù)sys_audit,它將把事先記錄的系統(tǒng) 調用序列信息(比如系統(tǒng)調用的進程號,命令等相關信息)返回給用戶空間。而 記錄這些系統(tǒng)調用序列則是依靠另

27、一個內核服務函數(shù)syscall_audit,該函數(shù)負責 搜集系統(tǒng)調用數(shù)據(jù)并填充到一個自建的內核緩沖區(qū)中,等待系統(tǒng)調用 audit 將搜 集到的內核數(shù)據(jù)取回到用戶空間。它的搜集方式很有意思。首先要修改系統(tǒng)調用處理程序system_call,在其中 需要監(jiān)控的每個調用(在我們例子鐘 222 個系統(tǒng)調用都監(jiān)控了,當然你也可以根 據(jù)自己需求有選擇的監(jiān)控)執(zhí)行完畢后都插入一個指令,該指令會轉去調用內核 服務函數(shù) syscall_audit 來記錄該次調用的信息。因為任何一個系統(tǒng)調用都要經(jīng)過 system_call 統(tǒng)一處理,所以任何一次系統(tǒng)調用的信息都可被 syscall_audit 記錄下 來。Syscall_audit 內核服務函數(shù)要做的事情就是記錄系統(tǒng)調用的信息,具體做法 是建立一個內核緩沖區(qū)來存放被記錄的函數(shù)。當搜集的數(shù)據(jù)量到達一定閥值時 (比如設定為到達緩沖區(qū)總大小的 80,這樣做可以避免再丟失新調用),喚醒 系統(tǒng)調用進程取回數(shù)據(jù)。否則繼續(xù)搜集,這時,系統(tǒng)調用程序會堵塞在一個等待 隊列上,直到被喚醒,也就是說,如果緩沖區(qū)還沒接近滿時,系統(tǒng)調用會等待它 被填充。Sys_audit 系統(tǒng)調用服務函數(shù)所做的事情很簡單,就是從緩沖區(qū)中取數(shù)據(jù)返回 用戶空間。如果緩沖還沒滿則掛起等待。道理就這么多了。不過為了方便調試,我們采用模塊化方式來加載 sys_audit 和sysca

溫馨提示

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

評論

0/150

提交評論