Linux系統調用詳細全過程_第1頁
Linux系統調用詳細全過程_第2頁
Linux系統調用詳細全過程_第3頁
Linux系統調用詳細全過程_第4頁
Linux系統調用詳細全過程_第5頁
已閱讀5頁,還剩37頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

1、LinuxLinux系統調用系統調用_ _詳細全過程詳細全過程u系統調用功能概述系統調用功能概述u系統調用的處理過程系統調用的處理過程u系統調用的實例分析系統調用的實例分析u如何增加一個系統調用如何增加一個系統調用 LinuxLinux系統調用系統調用_ _詳細全過程詳細全過程u系統調用系統調用( (SYSTEM CALL)SYSTEM CALL) nOSOS內核中都有一組實現系統功能的過程,內核中都有一組實現系統功能的過程,系統調用就是對上述過程的調用。編程人系統調用就是對上述過程的調用。編程人員利用系統調用,向員利用系統調用,向OSOS提出服務請求,由提出服務請求,由OSOS代為完成。代為

2、完成。u一般情況下,進程是不能夠存取系統內核一般情況下,進程是不能夠存取系統內核的。它不能存取內核使用的內存段,也不能的。它不能存取內核使用的內存段,也不能調用內核函數,調用內核函數,CPUCPU的硬件結構保證了這一的硬件結構保證了這一點。只有系統調用是一個例外。點。只有系統調用是一個例外。 Linux系統調用系統調用- -功能功能u系統調用是用戶態進入內核態的唯一入口系統調用是用戶態進入內核態的唯一入口:一夫一夫當關,萬夫莫開。常用系統調用:當關,萬夫莫開。常用系統調用:n控制硬件控制硬件: :如如write/readwrite/read調用。調用。n設置系統狀態或讀取內核數據設置系統狀態或

3、讀取內核數據getpid()getpid()、getpriority()getpriority()、setpriority()setpriority()、sethostname()sethostname()n進程管理進程管理: :如如 fork()fork()、clone()clone()、execve()execve()、exit()exit()等等u優點優點 n編程容易,從硬件設備的低級編程中解脫出來編程容易,從硬件設備的低級編程中解脫出來n提高了系統的安全性,可以先檢查請求的正確性提高了系統的安全性,可以先檢查請求的正確性5.1 Linux系統調用系統調用- -功能功能陷入指令系統子程序

4、sub 0A0sub 1A1sub nAnsub iAi.陷入處理機構1)保護處理機現場2)取系統調用功能號并尋找子程序入口3)恢復處理機現場并返回入口地址表A0A2Ai.An.系統調用.用戶程序5.2 Int 5.2 Int 0 x800 x80指令指令uLinuxLinux中實現系統調用利用了中實現系統調用利用了i386i386體系結體系結構中的軟件中斷。即調用了構中的軟件中斷。即調用了int $0 x80匯編指令。匯編指令。u這條匯編指令將產生向量為這條匯編指令將產生向量為128128的編程異的編程異常,常,CPUCPU便被切換到內核態執行內核函數,便被切換到內核態執行內核函數,轉到了系

5、統調用處理程序的入口:轉到了系統調用處理程序的入口:system_call()system_call()。uint $0 x80int $0 x80指令將用戶態的執行模式轉變為內指令將用戶態的執行模式轉變為內核態,并將控制權交給系統調用過程的起點核態,并將控制權交給系統調用過程的起點system_call()system_call()處理函數。處理函數。system_call()system_call()函數函數usystem_cal()system_cal()檢查系統調用號,該號碼告訴內核檢查系統調用號,該號碼告訴內核進程請求哪種服務。進程請求哪種服務。u內核進程查看系統調用表內核進程查看系

6、統調用表(sys_call_table)(sys_call_table)找到找到所調用的內核函數入口地址。所調用的內核函數入口地址。u接著調用相應的函數,在返回后做一些系統檢查,接著調用相應的函數,在返回后做一些系統檢查,最后返回到進程。最后返回到進程。系統調用和普通函數調用系統調用和普通函數調用uAPIAPI是用于某種特定目的的函數,供應用程序調用,是用于某種特定目的的函數,供應用程序調用,而系統調用供應用程序直接進入系統內核。而系統調用供應用程序直接進入系統內核。uLinuxLinux內核提供了一些內核提供了一些C C語言函數庫,這些庫對系統語言函數庫,這些庫對系統調用進行了一些包裝和擴展

7、,因為這些庫函數與系調用進行了一些包裝和擴展,因為這些庫函數與系統調用的關系非常緊密,所以習慣上把這些函數也統調用的關系非常緊密,所以習慣上把這些函數也稱為系統調用。稱為系統調用。u有的有的APIAPI函數在用戶空間就可以完成工作,如一些函數在用戶空間就可以完成工作,如一些用于數學計算的函數,因此不需要使用系統調用。用于數學計算的函數,因此不需要使用系統調用。u有的有的APIAPI函數可能會進行多次系統調用。函數可能會進行多次系統調用。u不同的不同的API API 函數也可能會有相同的系統調用。比如函數也可能會有相同的系統調用。比如malloc()malloc(),calloc()calloc

8、(),free()free()等函數都使用相同的等函數都使用相同的方法分配和釋放內存。方法分配和釋放內存。系統命令、內核函數系統命令、內核函數u系統調用與系統命令系統調用與系統命令n系統命令相對系統命令相對APIAPI來說,更高一層。每個系統命令來說,更高一層。每個系統命令都是一個執行程序,如都是一個執行程序,如lsls命令等。這些命令的實現命令等。這些命令的實現調用了系統調用。調用了系統調用。u系統調用與內核函數系統調用與內核函數n系統調用是用戶進入內核的接口層,它本身并非內系統調用是用戶進入內核的接口層,它本身并非內核函數,但是它由內核函數實現。核函數,但是它由內核函數實現。n進入內核后,

9、不同的系統調用會找到各自對應的內進入內核后,不同的系統調用會找到各自對應的內核函數,這些內核函數被稱為系統調用的核函數,這些內核函數被稱為系統調用的“服務例服務例程程”。如系統調用。如系統調用getpidgetpid實際調用的服務例程為實際調用的服務例程為sys_getpid()sys_getpid(),或者說系統調用,或者說系統調用getpid()getpid()是服務例是服務例程程sys_getpid()sys_getpid()的封裝例程。的封裝例程。封裝例程封裝例程(wrapper routine)(wrapper routine)u由于陷入指令是一條特殊指令,依賴操作系統實現由于陷入指

10、令是一條特殊指令,依賴操作系統實現的平臺,如在的平臺,如在i386i386體系結構中,這條指令是體系結構中,這條指令是int int $0 x80($0 x80(陷入指令陷入指令) ),不是用戶在編程時應該使用的,不是用戶在編程時應該使用的語句,因為這將使得用戶程序難于移植。語句,因為這將使得用戶程序難于移植。u在標準在標準C C庫函數庫函數中,為每個系統調用設置了一個中,為每個系統調用設置了一個封封裝例程裝例程,當一個用戶程序執行了一個系統調用時,當一個用戶程序執行了一個系統調用時,就會調用到就會調用到C C函數庫中的相對應的封裝例程。函數庫中的相對應的封裝例程。系統調用過程系統調用過程系統

11、調用過程系統調用過程xyz()system_call: sys_xyz() ret_from_sys_call:iretxyz()int 0 x80sys_xyz()在應用程序在應用程序 在標準庫在標準庫 系統調用系統調用 系統調用系統調用調用中的調用中的 中的封裝例程中的封裝例程 處理程序處理程序 服務例程服務例程系統調用系統調用用戶態用戶態 內核態內核態system_call()system_call()函數(見教材函數(見教材P234P234頁)頁)u首先將系統調用號首先將系統調用號(eax)(eax)和可以用到的所有和可以用到的所有CPUCPU寄存寄存器保存到相應的堆棧中(由器保存到相

12、應的堆棧中(由SAVE_ALLSAVE_ALL完成);完成);u對用戶態進程傳遞過來的系統調用號進行有效性檢對用戶態進程傳遞過來的系統調用號進行有效性檢查查(eax(eax是系統調用號,它應該小于是系統調用號,它應該小于 NR_syscallsNR_syscalls)u如果是合法的系統調用,再進一步檢測該系統調用如果是合法的系統調用,再進一步檢測該系統調用是否正被跟蹤;是否正被跟蹤;u根據根據eaxeax中的系統調用號調用相應的服務例程。中的系統調用號調用相應的服務例程。u服務例程結束后,從服務例程結束后,從eaxeax寄存器獲得它的返回值,寄存器獲得它的返回值,并把這個返回值存放在堆棧中,讓

13、其位于用戶態并把這個返回值存放在堆棧中,讓其位于用戶態eaxeax寄存器曾存放的位置。寄存器曾存放的位置。u然后跳轉到然后跳轉到ret_from_sys_call()ret_from_sys_call(),終止系統調用,終止系統調用程序的執行。程序的執行。SAVE_ALLSAVE_ALL宏定義宏定義 #define SAVE_ALL #define SAVE_ALL cld; cld; pushl %es; pushl %es; pushl %ds; pushl %ds; pushl %eax; pushl %eax; pushl %ebp; pushl %ebp; pushl %edi; p

14、ushl %edi; pushl %esi; pushl %esi; pushl %edx; pushl %edx; pushl %ecx; pushl %ecx; pushl %ebx; pushl %ebx; movl $(_KERNEL_DS),%edx; movl $(_KERNEL_DS),%edx; movl %edx,%ds; movl %edx,%ds; movl %edx,%es;movl %edx,%es; 將寄存器中的參數壓入到將寄存器中的參數壓入到核心棧中核心棧中( (這樣內核才能使這樣內核才能使用用戶傳入的參數。用用戶傳入的參數。) ) 因為在不同特權級之間控因為在不

15、同特權級之間控制轉換時,制轉換時,INTINT指令不同于指令不同于CALLCALL指令,它不會將外層指令,它不會將外層堆棧的參數自動拷貝到內堆棧的參數自動拷貝到內層堆棧中。層堆棧中。所以在調用系所以在調用系統調用時,必須把參數指統調用時,必須把參數指定到各個寄存器中定到各個寄存器中圖10.2 調用總控程序(system_call)執行流程圖系統調用表與調用號u這樣系統調用處理程序一旦運行,就可以從這樣系統調用處理程序一旦運行,就可以從eaxeax中中得到系統調用號,然后再去系統調用表中尋找相得到系統調用號,然后再去系統調用表中尋找相應服務例程。應服務例程。u 一個應用程序調用一個應用程序調用f

16、ork()fork()封裝例程,那么在執行封裝例程,那么在執行int $0 x80int $0 x80之前就把之前就把eaxeax寄存器的值置為寄存器的值置為2(2(即即_NR_fork)_NR_fork)。u這個寄存器的設置是這個寄存器的設置是libclibc庫中的封裝例程進行的,庫中的封裝例程進行的,因此用戶一般不關心系統調用號因此用戶一般不關心系統調用號系統調用表與調用號u核心中為每個系統調用定義了一個唯一的編號,這個編號核心中為每個系統調用定義了一個唯一的編號,這個編號的定義在的定義在linux/include/asm/unistd.hlinux/include/asm/unistd.

17、h中(最大為中(最大為NR_syscallNR_syscall)u同時在內核中保存了一張同時在內核中保存了一張系統調用表,該表中保存了系統系統調用表,該表中保存了系統調用編號和其對應的服務例程地址調用編號和其對應的服務例程地址。第第n n個表項包含系統個表項包含系統調用號為調用號為n n的服務例程的地址。的服務例程的地址。u系統調用陷入內核前,需要把系統調用號一起傳入內核。系統調用陷入內核前,需要把系統調用號一起傳入內核。而該標號實際上是系統調用表而該標號實際上是系統調用表( ( sys_call_tablesys_call_table) )的下標的下標u在在i386i386上,這個傳遞動作是

18、通過在執行上,這個傳遞動作是通過在執行int $0 x80int $0 x80前前把調把調用號裝入用號裝入eaxeax寄存器寄存器實現。實現。u這樣系統調用處理程序一旦運行,就可以從這樣系統調用處理程序一旦運行,就可以從eaxeax中得到系中得到系統調用號,然后再去系統調用表中尋找相應服務例程。統調用號,然后再去系統調用表中尋找相應服務例程。系統調用號系統調用號u#define _NR_exit 1u#define _NR_fork 2u#define _NR_read 3u#define _NR_write 4u#define _NR_open 5u#define _NR_close 6u#

19、define _NR_waitpid 7u#define _NR_creat 8u#define _NR_link 9u#define _NR_unlink 10u#define _NR_execve 11u#define _NR_chdir 12u#define _NR_time 13系統調用表系統調用表 (arch/i386/kernel/entry.s)u dataENTRY(sys_call_table).long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_exit).long SYMBOL_NAME(sys_fork).lon

20、g SYMBOL_NAME(sys_read).long SYMBOL_NAME(sys_write).long SYMBOL_NAME(sys_open) .long SYMBOL_NAME(sys_close).long SYMBOL_NAME(sys_waitpid).long SYMBOL_NAME(sys_creat).long SYMBOL_NAME(sys_link).long SYMBOL_NAME(sys_unlink) .long SYMBOL_NAME(sys_execve).long SYMBOL_NAME(sys_chdir).long SYMBOL_NAME(sys

21、_time).long SYMBOL_NAME(sys_mknod) 系統調用表系統調用表記錄了各個記錄了各個系統調用的服務例程的系統調用的服務例程的入口地址。入口地址。 以系統調用號為偏移量以系統調用號為偏移量能夠在該表中找到對應能夠在該表中找到對應處理函數地址。處理函數地址。 在在linux/include/linuxlinux/include/linux/sys.h/sys.h中定義的中定義的NR_syscallsNR_syscalls表示該表表示該表能容納的最大系統調用能容納的最大系統調用數,一般數,一般NR_syscalls NR_syscalls = 256= 256。系統調用表(

22、sys_call_table)系統調用的返回系統調用的返回u當服務例程結束時,system_call( ) 從eax獲得系統調用的返回值,并把這個返回值存放在曾保存用戶態 eax寄存器棧單元的那個位置上,然后跳轉到ret_from_sys_call( ),終止系統調用處理程序的執行。u當進程恢復它在用戶態的執行前,RESTORE_ALL宏會恢復用戶進入內核前被保留到堆棧中的寄存器值。其中eax返回時會帶回系統調用的返回碼(負數說明調用錯誤,0或正數說明正常完成)系統調用的返回值系統調用的返回值u所有的系統調用返回一個整數值。所有的系統調用返回一個整數值。n正數或正數或0 0表示系統調用成功結束

23、表示系統調用成功結束n負數表示一個出錯條件負數表示一個出錯條件u這里的返回值與封裝例程返回值的約定不同這里的返回值與封裝例程返回值的約定不同n內核沒有設置或使用內核沒有設置或使用errnoerrno變量變量n封裝例程在系統調用返回取得返回值之后設置這封裝例程在系統調用返回取得返回值之后設置這個變量個變量n當系統調用出錯時,返回的那個負值將要存放在當系統調用出錯時,返回的那個負值將要存放在errnoerrno變量中返回給應用程序變量中返回給應用程序5.3 5.3 系統調用系統調用- -實例分析實例分析假設源文件名為假設源文件名為getpid.cgetpid.c,內容是:,內容是:#include

24、 #include #include #include #include #include #include #include int main(void) int main(void) long ID; long ID; ID = getpid(); ID = getpid(); printf (getpid()=%ldn, ID); printf (getpid()=%ldn, ID); return(0); return(0); 系統調用系統調用- -實例分析實例分析u 該程序調用封裝例程該程序調用封裝例程getpid()getpid()。該封裝例程將。該封裝例程將系統調用號系統調用號_

25、NR_getpid_NR_getpid(第(第2020個)壓入個)壓入EAXEAX寄存寄存器器uCPUCPU通過通過int $0 x80 int $0 x80 進入內核,找到進入內核,找到system_call()system_call(),并調用它,并調用它 (以下進入內核態)(以下進入內核態)3. 3. 在內核中首先執行在內核中首先執行system_call()system_call(),接著執行,接著執行根據系統調用號在調用表中查找到的對應的系根據系統調用號在調用表中查找到的對應的系統調用服務例程統調用服務例程sys_getpid()sys_getpid()。4 4執行執行syssys_

26、 _getpid()getpid()服務例程。服務例程。5 5執行完畢后,轉入執行完畢后,轉入ret_from_sys_call()ret_from_sys_call()例程,例程,系統調用返回到用戶態。系統調用返回到用戶態。5.4 5.4 系統調用的參數傳遞系統調用的參數傳遞u很多系統調用需要不止一個參數很多系統調用需要不止一個參數n普通普通C C函數的參數傳遞是通過把參數值寫入堆棧函數的參數傳遞是通過把參數值寫入堆棧( (用用戶態堆棧或內核態堆棧戶態堆棧或內核態堆棧) )來實現的。但因為系統調來實現的。但因為系統調用是一種特殊函數,它由用戶態進入了內核態,所用是一種特殊函數,它由用戶態進入

27、了內核態,所以以既不能使用用戶態的堆棧也不能直接使用內核態既不能使用用戶態的堆棧也不能直接使用內核態堆棧堆棧用戶態堆棧用戶態C函數內核態堆棧內核態C函數系統調用的參數傳遞系統調用的參數傳遞n在在int $0 x80int $0 x80匯編指令之前,系統調用的參數被寫匯編指令之前,系統調用的參數被寫入入CPUCPU的的寄存器寄存器。然后,在進入內核態調用系統調。然后,在進入內核態調用系統調用服務例程之前,內核再把存放在用服務例程之前,內核再把存放在CPUCPU寄存器中的寄存器中的參數拷貝到內核態堆棧中。因為畢竟服務例程是參數拷貝到內核態堆棧中。因為畢竟服務例程是C C函數,它還是要到堆棧中去尋找

28、參數的函數,它還是要到堆棧中去尋找參數的用戶態堆棧用戶態C函數內核態堆棧內核態C函數寄存器系統調用的參數傳遞系統調用的參數傳遞系統調用系統調用使用寄存器來傳遞參數使用寄存器來傳遞參數,要傳遞的參數有:,要傳遞的參數有:系統調用號系統調用號系統調用所需的參數系統調用所需的參數用于傳遞參數的寄存器有:用于傳遞參數的寄存器有:eaxeax:用于保存系統調用號和系統調用返回值:用于保存系統調用號和系統調用返回值系統調用參數保存在:系統調用參數保存在:ebx,ecx,edx,esiebx,ecx,edx,esi和和ediedi中中進入內核態后,進入內核態后,system_callsystem_call通

29、過使用通過使用SAVE_ALLSAVE_ALL宏把這宏把這些寄存器的值保存在內核態堆棧中。些寄存器的值保存在內核態堆棧中。n用寄存器傳遞參數必須滿足兩個條件:用寄存器傳遞參數必須滿足兩個條件:n 每個參數的長度不能超過寄存器的長度每個參數的長度不能超過寄存器的長度n 參數的個數不能超過參數的個數不能超過6 6個個( (包括包括eaxeax中傳遞中傳遞的系統調用號的系統調用號););否則,需要用一個單獨的否則,需要用一個單獨的寄存器指向進程地址空間中這些參數值所寄存器指向進程地址空間中這些參數值所在的一個內存區即可在的一個內存區即可n返回值必須寫到返回值必須寫到eaxeax寄存器中寄存器中系統調

30、用的參數傳遞系統調用的參數傳遞參數傳遞舉例參數傳遞舉例u 處理處理writewrite系統調用的系統調用的sys_writesys_write服務例程聲明如下服務例程聲明如下u 該函數期望在棧頂找到該函數期望在棧頂找到fdfd,bufbuf和和countcount參數參數在封裝在封裝sys_write()sys_write()的封裝例程中,將會在的封裝例程中,將會在ebxebx、ecxecx和和edxedx寄存寄存器中分別填入這些參數的值,然后在進入器中分別填入這些參數的值,然后在進入system_callsystem_call時,時,SAVE_ALLSAVE_ALL會把這些寄存器保存在堆棧中

31、,進入會把這些寄存器保存在堆棧中,進入sys_writesys_write服務例服務例程后,就可以在相應的位置找到這些參數程后,就可以在相應的位置找到這些參數asmlinkage使得編譯器不通過寄存器(x=0)而使用堆棧傳遞參數SAVE_ALLSAVE_ALLSys_write需要的參數系統調用的參數傳遞系統調用的參數傳遞- -舉例設設C庫中封裝的系統調用號為庫中封裝的系統調用號為3的函數原形如下:的函數原形如下: int sys_func(int para1, int para2)C編譯器產生的匯編偽碼如:編譯器產生的匯編偽碼如:movl 0 x8(%esp),%ecx /*將用戶態堆棧中的

32、將用戶態堆棧中的para2放入放入ecxMovl 0 x4(%esp),%ebx /*#將用戶態堆棧中的將用戶態堆棧中的para1放入放入ebxMovl $0 x3,%eax /*系統調用號保存在系統調用號保存在eax中中int$0 x80 #引發系統調用引發系統調用Movl %eax,errno /*將結果存入全局變量將結果存入全局變量errno中中Movl $-1,%eax /*eax置為置為-1,表示出錯注,表示出錯注5.5 5.5 練習:練習:添加一個系統調用添加一個系統調用mysyscallmysyscallu功能要求功能要求 首先,自定義一個系統調用首先,自定義一個系統調用mysy

33、scallmysyscall ,它的功,它的功能是使用戶的能是使用戶的uiduid等于等于0 0 。然后,編寫一段測試程。然后,編寫一段測試程序進行調用。序進行調用。u執行步驟如下執行步驟如下n添加系統調用號添加系統調用號n在系統調用表中添加相應的表項在系統調用表中添加相應的表項n實現系統調用服務例程實現系統調用服務例程n重新編譯內核,啟動新內核重新編譯內核,啟動新內核n編寫一段測試程序檢驗實驗結果編寫一段測試程序檢驗實驗結果添加一個系統調用添加一個系統調用mysyscallmysyscall(1 1)添加系統調用號:)添加系統調用號:它位于它位于unistd.hunistd.h,每個系統調用

34、號,每個系統調用號都以都以“_NR_NR_開頭開頭”,u系統調用的編號命名為系統調用的編號命名為 _NR_mysyscall_NR_mysyscallu改寫改寫/usr/include/asm/unistd.h/usr/include/asm/unistd.h240240 #define #define _NR_llistxattr_NR_llistxattr 233233241241 #define #define _NR_flistxattr_NR_flistxattr 234234242242 #define #define _NR_removexattr_NR_removexattr

35、235235243243 #define #define _NR_lremovexattr_NR_lremovexattr 236236244244 #define #define _NR_fremovexattr_NR_fremovexattr 237237245245 #define #define _NR_mysyscall238238添加一個系統調用添加一個系統調用mysyscallmysyscall(2 2)在系統調用表中添加相應的表項)在系統調用表中添加相應的表項u內核中實現該系統調用的例程的名字內核中實現該系統調用的例程的名字 sys_mysyscallsys_mysyscall

36、u改寫改寫arch/i386/kernel/entry.Sarch/i386/kernel/entry.S398398 ENTRY(sys_call_table) ENTRY(sys_call_table)399399 .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_ni_syscall) 636636 .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_ni_syscall) 637 637 .long SYMBOL_NAME(sys_mysyscall).long SYMBOL_NAME(sys_mysyscall)638 638 639 .rept NR_syscalls-(.-sys_call_table)/4639 .rept NR_syscalls-(.-sys_call_table)/46 640 .long SYMBOL_NAME(sys_ni_syscall)40 .long SYMBOL_NAME(sys_ni_syscall)64641 .endr 1 .endr 添加一個系統調用添加一個系統調用mysyscallmysyscal

溫馨提示

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

評論

0/150

提交評論