Linux之信號(hào)量,比較全面,個(gè)人總結(jié)_第1頁
Linux之信號(hào)量,比較全面,個(gè)人總結(jié)_第2頁
Linux之信號(hào)量,比較全面,個(gè)人總結(jié)_第3頁
Linux之信號(hào)量,比較全面,個(gè)人總結(jié)_第4頁
Linux之信號(hào)量,比較全面,個(gè)人總結(jié)_第5頁
已閱讀5頁,還剩14頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、信號(hào)量一什么是信號(hào)量信號(hào)量的使用主要是用來保護(hù)共享資源,使得資源在一個(gè)時(shí)刻只有一個(gè)進(jìn)程(線程)所擁有。信號(hào)量的值為正的時(shí)候,說明它空閑。所測(cè)試的線程可以鎖定而使用它。若為0,說明它被占用,測(cè)試的線程要進(jìn)入睡眠隊(duì)列中,等待被喚醒。二信號(hào)量的分類在學(xué)習(xí)信號(hào)量之前,我們必須先知道Linux提供兩種信號(hào)量:POSIX信號(hào)量又分為有名信號(hào)量和無名信號(hào)量。有名信號(hào)量,其值保存在文件中, 所以它可以用于線程也可以用于進(jìn)程間的同步。無名信號(hào)量,其值保存在內(nèi)存中。倘若對(duì)信號(hào)量沒有以上的全面認(rèn)識(shí)的話,你就會(huì)很快發(fā)現(xiàn)自己在信號(hào)量的森林里迷失了方向。三內(nèi)核信號(hào)量1內(nèi)核信號(hào)量的構(gòu)成內(nèi)核信號(hào)量類似于自旋鎖,因?yàn)楫?dāng)鎖關(guān)閉著

2、時(shí),它不允許內(nèi)核控制路徑繼續(xù)進(jìn)行。然而,當(dāng)內(nèi)核控制路徑試圖獲取內(nèi)核信號(hào)量鎖保護(hù)的忙資源時(shí),相應(yīng)的進(jìn)程就被掛起。只有在資源被釋放時(shí),進(jìn)程才再次變?yōu)榭蛇\(yùn)行。只有可以睡眠的函數(shù)才能獲取內(nèi)核信號(hào)量;中斷處理程序和可延遲函數(shù)都不能使用內(nèi)核信號(hào)量。count:相當(dāng)于信號(hào)量的值,大于0,資源空閑;等于0,資源忙,但沒有進(jìn)程等待這個(gè)保護(hù)的資源;小于0,資源不可用,并至少有一個(gè)進(jìn)程等待資源。wait:存放等待隊(duì)列鏈表的地址,當(dāng)前等待資源的所有睡眠進(jìn)程都會(huì)放在這個(gè)鏈表中。 sleepers:存放一個(gè)標(biāo)志,表示是否有一些進(jìn)程在信號(hào)量上睡眠。2內(nèi)核信號(hào)量中的等待隊(duì)列(刪除,沒有聯(lián)系)上面已經(jīng)提到了內(nèi)核信號(hào)量使用了等待

3、隊(duì)列wait_queue來實(shí)現(xiàn)阻塞操作。當(dāng)某任務(wù)由于沒有某種條件沒有得到滿足時(shí),它就被掛到等待隊(duì)列中睡眠。當(dāng)條件得到滿足時(shí),該任務(wù)就被移出等待隊(duì)列,此時(shí)并不意味著該任務(wù)就被馬上執(zhí)行,因?yàn)樗直灰七M(jìn)工作隊(duì)列中等待CPU資源,在適當(dāng)?shù)臅r(shí)機(jī)被調(diào)度。內(nèi)核信號(hào)量是在內(nèi)部使用等待隊(duì)列的,也就是說該等待隊(duì)列對(duì)用戶是隱藏的,無須用戶干涉。由用戶真正使用的等待隊(duì)列我們將在另外的篇章進(jìn)行詳解。3內(nèi)核信號(hào)量的相關(guān)函數(shù)(1)初始化:(2)申請(qǐng)內(nèi)核信號(hào)量所保護(hù)的資源:(3)釋放內(nèi)核信號(hào)量所保護(hù)的資源:4內(nèi)核信號(hào)量的使用例程在驅(qū)動(dòng)程序中,當(dāng)多個(gè)線程同時(shí)訪問相同的資源時(shí)(驅(qū)動(dòng)中的全局變量時(shí)一種典型的共享資源),可能會(huì)引發(fā)“

4、競(jìng)態(tài)“,因此我們必須對(duì)共享資源進(jìn)行并發(fā)控制。Linux內(nèi)核中解決并發(fā)控制的最常用方法是自旋鎖與信號(hào)量(絕大多數(shù)時(shí)候作為互斥鎖使用)。四POSIX 信號(hào)量與SYSTEM V信號(hào)量的比較1. 對(duì)POSIX來說,信號(hào)量是個(gè)非負(fù)整數(shù)。常用于線程間同步。而SYSTEM V信號(hào)量則是一個(gè)或多個(gè)信號(hào)量的集合,它對(duì)應(yīng)的是一個(gè)信號(hào)量結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體是為SYSTEM V IPC服務(wù)的,信號(hào)量只不過是它的一部分。常用于進(jìn)程間同步。2POSIX信號(hào)量的引用頭文件是“<semaphore.h>”,而SYSTEM V信號(hào)量的引用頭文件是“<sys/sem.h>”。3從使用的角度,System V

5、信號(hào)量是復(fù)雜的,而Posix信號(hào)量是簡(jiǎn)單。比如,POSIX信號(hào)量的創(chuàng)建和初始化或PV操作就很非常方便。五POSIX信號(hào)量詳解1無名信號(hào)量無名信號(hào)量的創(chuàng)建就像聲明一般的變量一樣簡(jiǎn)單,例如:sem_t sem_id。然后再初始化該無名信號(hào)量,之后就可以放心使用了。無名信號(hào)量常用于多線程間的同步,同時(shí)也用于相關(guān)進(jìn)程間的同步。也就是說,無名信號(hào)量必須是多個(gè)進(jìn)程(線程)的共享變量,無名信號(hào)量要保護(hù)的變量也必須是多個(gè)進(jìn)程(線程)的共享變量,這兩個(gè)條件是缺一不可的。常見的無名信號(hào)量相關(guān)函數(shù):sem_destroy注意:在這些函數(shù)中,只有sem_post是信號(hào)安全的函數(shù),它是可重入函數(shù)(a)無名信號(hào)量在多線程

6、間的同步無名信號(hào)量的常見用法是將要保護(hù)的變量放在sem_wait和sem_post中間所形成的臨界區(qū)內(nèi),這樣該變量就會(huì)被保護(hù)起來,例如:上面的例程,到底哪個(gè)線程先申請(qǐng)到信號(hào)量資源,這是隨機(jī)的。如果想要某個(gè)特定的順序的話,可以用2個(gè)信號(hào)量來實(shí)現(xiàn)。例如下面的例程是線程1先執(zhí)行完,然后線程2才繼(b)無名信號(hào)量在相關(guān)進(jìn)程間的同步說是相關(guān)進(jìn)程,是因?yàn)楸境绦蛑泄灿?個(gè)進(jìn)程,其中一個(gè)是另外一個(gè)的子進(jìn)程(由fork 產(chǎn)生)的。本來對(duì)于fork來說,子進(jìn)程只繼承了父進(jìn)程的代碼副本,mutex理應(yīng)在父子進(jìn)程中是相互獨(dú)立的兩個(gè)變量,但由于在初始化mutex的時(shí)候,由pshared = 1指定了mutex處于共享內(nèi)

7、存區(qū)域,所以此時(shí)mutex變成了父子進(jìn)程共享的一個(gè)變量。此時(shí),mutex就可以用來同步相關(guān)進(jìn)程了。/open a file and map it into memoryfd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);write(fd,&zero,sizeof(int);ptr = mmap( NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 );close(fd);/* create, initialize semaphore */if( sem_init(&m

8、utex,1,1) < 0) /perror("semaphore initilization");exit(0);if (fork() = 0) /* child process*/for (i = 0; i < nloop; i+)sem_wait(&mutex);printf("child: %dn", (*ptr)+);sem_post(&mutex);exit(0);/* back to parent process */for (i = 0; i < nloop; i+)sem_wait(&mutex

9、);printf("parent: %dn", (*ptr)+);sem_post(&mutex);exit(0);2有名信號(hào)量有名信號(hào)量的特點(diǎn)是把信號(hào)量的值保存在文件中。這決定了它的用途非常廣:既可以用于線程,也可以用于相關(guān)進(jìn)程間,甚至是不相關(guān)進(jìn)程。(a)有名信號(hào)量能在進(jìn)程間共享的原因由于有名信號(hào)量的值是保存在文件中的,所以對(duì)于相關(guān)進(jìn)程來說,子進(jìn)程是繼承了父進(jìn)程的文件描述符,那么子進(jìn)程所繼承的文件描述符所指向的文件是和父進(jìn)程一樣的,當(dāng)然文件里面保存的有名信號(hào)量值就共享了。(b)有名信號(hào)量相關(guān)函數(shù)說明有名信號(hào)量在使用的時(shí)候,和無名信號(hào)量共享sem_wait和sem_

10、post函數(shù)。區(qū)別是有名信號(hào)量使用sem_open代替sem_init,另外在結(jié)束的時(shí)候要像關(guān)閉文件一樣去關(guān)閉這個(gè)有名信號(hào)量。(1)打開一個(gè)已存在的有名信號(hào)量,或創(chuàng)建并初始化一個(gè)有名信號(hào)量。一個(gè)單一的調(diào)用就完成了信號(hào)量的創(chuàng)建、初始化和權(quán)限的設(shè)置。這里的name不能寫成/tmp/aaa.sem這樣的格式,因?yàn)樵趌inux下,sem都是創(chuàng)建在/dev/shm目錄下。你可以將name寫成“/mysem”或“mysem”,創(chuàng)建出來的文件都是“/dev/shm/sem.mysem”,千萬不要寫路徑。也千萬不要寫“/tmp/mysem”之類的。當(dāng)oflag = O_CREAT時(shí),若name指定的信號(hào)量不存

11、在時(shí),則會(huì)創(chuàng)建一個(gè),而且后面的mode和value參數(shù)必須有效。若name指定的信號(hào)量已存在,則直接打開該信號(hào)量,同時(shí)忽略mode和value參數(shù)。當(dāng)oflag = O_CREAT|O_EXCL時(shí),若name指定的信號(hào)量已存在,該函數(shù)會(huì)直接返回error。(2) 一旦你使用了一信號(hào)量,銷毀它們就變得很重要。在做這個(gè)之前,要確定所有對(duì)這個(gè)有名信號(hào)量的引用都已經(jīng)通過sem_close()函數(shù)關(guān)閉了,然后只需在退出或是退出處理函數(shù)中調(diào)用sem_unlink()去刪除系統(tǒng)中的信號(hào)量,注意如果有任何的處理器或是線程引用這個(gè)信號(hào)量,sem_unlink()函數(shù)不會(huì)起到任何的作用。也就是說,必須是最后一個(gè)使

12、用該信號(hào)量的進(jìn)程來執(zhí)行sem_unlick才有效。因?yàn)槊總€(gè)信號(hào)燈有一個(gè)引用計(jì)數(shù)器記錄當(dāng)前的打開次數(shù),sem_unlink必須等待這個(gè)數(shù)為0時(shí)才能把name所指的信號(hào)燈從文件系統(tǒng)中刪除。也就是要等待最后一個(gè)sem_close發(fā)生。 (c)有名信號(hào)量在無相關(guān)進(jìn)程間的同步前面已經(jīng)說過,有名信號(hào)量是位于共享內(nèi)存區(qū)的,那么它要保護(hù)的資源也必須是位于共享內(nèi)存區(qū),只有這樣才能被無相關(guān)的進(jìn)程所共享。在下面這個(gè)例子中,服務(wù)進(jìn)程和客戶進(jìn)程都使用shmget和shmat來獲取得一塊共享內(nèi)存資源。然后利用有名信號(hào)量來對(duì)這塊共享內(nèi)存資源進(jìn)行互斥保護(hù)。#include <sys/types.h>#includ

13、e <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define SHMSZ 27char SEM_NAME= "vik"int main()char ch;int shmid;key_t key;char *shm,*s;sem_t *mutex;/name the shar

14、ed memory segmentkey = 1000;/create & initialize semaphoremutex = sem_open(SEM_NAME,O_CREAT,0644,1); if(mutex = SEM_FAILED)perror("unable to create semaphore"); sem_unlink(SEM_NAME);exit(-1);/create the shared memory segment with this key shmid = shmget(key,SHMSZ,IPC_CREAT|0666); if(sh

15、mid<0)perror("failure in shmget");exit(-1);/attach this segment to virtual memory shm = shmat(shmid,NULL,0);/start writing into memorys = shm;for(ch='A'ch<='Z'ch+)sem_wait(mutex);*s+ = ch;sem_post(mutex);/the below loop could be replaced by binary semaphore while(*shm

16、 != '*')sleep(1);sem_close(mutex);sem_unlink(SEM_NAME);shmctl(shmid, IPC_RMID, 0);exit(0);<u>File 2: client.c</u>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#includ

17、e <sys/stat.h>#include <fcntl.h>#define SHMSZ 27char SEM_NAME= "vik"int main()char ch;int shmid;key_t key;char *shm,*s;sem_t *mutex;/name the shared memory segmentkey = 1000;/create & initialize existing semaphoremutex = sem_open(SEM_NAME,0,0644,0);if(mutex = SEM_FAILED)per

18、ror("reader:unable to execute semaphore");sem_close(mutex);exit(-1);/create the shared memory segment with this keyshmid = shmget(key,SHMSZ,0666);if(shmid<0)perror("reader:failure in shmget");exit(-1);/attach this segment to virtual memoryshm = shmat(shmid,NULL,0);/start readi

19、ngs = shm;for(s=shm;*s!=NULL;s+)sem_wait(mutex);putchar(*s);sem_post(mutex);semaphore*shm = '*'sem_close(mutex);shmctl(shmid, IPC_RMID, 0);exit(0);六SYSTEM V信號(hào)量這是信號(hào)量值的集合,而不是單個(gè)信號(hào)量。相關(guān)的信號(hào)量操作函數(shù)由<sys/ipc.h>引用。1信號(hào)量結(jié)構(gòu)體內(nèi)核為每個(gè)信號(hào)量集維護(hù)一個(gè)信號(hào)量結(jié)構(gòu)體,可在<sys/sem.h>找到該定義:2常見的SYSTEM V信號(hào)量函數(shù)(a)關(guān)鍵字和描述符SYST

20、EM V信號(hào)量是SYSTEM V IPC(即SYSTEM V進(jìn)程間通信)的組成部分,其他的有SYSTEM V消息隊(duì)列,SYSTEM V共享內(nèi)存。而關(guān)鍵字和IPC描述符無疑是它們的共同點(diǎn),也使用它們,就不得不先對(duì)它們進(jìn)行熟悉。這里只對(duì)SYSTEM V信號(hào)量進(jìn)行討論。 IPC描述符相當(dāng)于引用ID號(hào),要想使用SYSTEM V信號(hào)量(或MSG、SHM),就必須用IPC描述符來調(diào)用信號(hào)量。而IPC描述符是內(nèi)核動(dòng)態(tài)提供的(通過semget來獲?。?,用戶無法讓服務(wù)器和客戶事先認(rèn)可共同使用哪個(gè)描述符,所以有時(shí)候就需要到關(guān)鍵字KEY來定位描述符。某個(gè)KEY只會(huì)固定對(duì)應(yīng)一個(gè)描述符(這項(xiàng)轉(zhuǎn)換工作由內(nèi)核完成),這樣假

21、如服務(wù)器和客戶事先認(rèn)可共同使用某個(gè)KEY,那么大家就都能定位到同一個(gè)描述符,也就能定位到同一個(gè)信號(hào)量,這樣就達(dá)到了SYSTEM V信號(hào)量在進(jìn)程間共享的目的。(b)創(chuàng)建和打開信號(hào)量semget函數(shù)執(zhí)行成功后,就產(chǎn)生了一個(gè)由內(nèi)核維持的類型為semid_ds結(jié)構(gòu)體的信號(hào)量集,返回semid就是指向該信號(hào)量集的引索。(c)關(guān)鍵字的獲取有多種方法使客戶機(jī)和服務(wù)器在同一IPC結(jié)構(gòu)上會(huì)合:(1) 服務(wù)器可以指定關(guān)鍵字IPC_PRIVATE創(chuàng)建一個(gè)新IPC結(jié)構(gòu),將返回的標(biāo)識(shí)符存放在某處(例如一個(gè)文件)以便客戶機(jī)取用。關(guān)鍵字 IPC_PRIVATE保證服務(wù)器創(chuàng)建一個(gè)新IPC結(jié)構(gòu)。這種技術(shù)的缺點(diǎn)是:服務(wù)器要將整型

22、標(biāo)識(shí)符寫到文件中,然后客戶機(jī)在此后又要讀文件取得此標(biāo)識(shí)符。IPC_PRIVATE關(guān)鍵字也可用于父、子關(guān)系進(jìn)程。父進(jìn)程指定 IPC_PRIVATE創(chuàng)建一個(gè)新IPC結(jié)構(gòu),所返回的標(biāo)識(shí)符在fork后可由子進(jìn)程使用。子進(jìn)程可將此標(biāo)識(shí)符作為exec函數(shù)的一個(gè)參數(shù)傳給一個(gè)新程序。(2) 在一個(gè)公用頭文件中定義一個(gè)客戶機(jī)和服務(wù)器都認(rèn)可的關(guān)鍵字。然后服務(wù)器指定此關(guān)鍵字創(chuàng)建一個(gè)新的IPC結(jié)構(gòu)。這種方法的問題是該關(guān)鍵字可能已與一個(gè) IPC結(jié)構(gòu)相結(jié)合,在此情況下,get函數(shù)(msgget、semget或shmget)出錯(cuò)返回。服務(wù)器必須處理這一錯(cuò)誤,刪除已存在的IPC結(jié)構(gòu),然后試著再創(chuàng)建它。當(dāng)然,這個(gè)關(guān)鍵字不能被別

23、的程序所占用。(3) 客戶機(jī)和服務(wù)器認(rèn)同一個(gè)路徑名和課題I D(課題I D是0 2 5 5之間的字符值) ,然后調(diào)用函數(shù)ftok將這兩個(gè)值變換為一個(gè)關(guān)鍵字。這樣就避免了使用一個(gè)已被占用的關(guān)鍵字的問題。使用ftok并非高枕無憂。有這樣一種例外:服務(wù)器使用ftok獲取得一個(gè)關(guān)鍵字后,該文件就被刪除了,然后重建。此時(shí)客戶端以此重建后的文件來ftok所獲取的關(guān)鍵字就和服務(wù)器的關(guān)鍵字不一樣了。所以一般商用的軟件都不怎么用ftok。一般來說,客戶機(jī)和服務(wù)器至少共享一個(gè)頭文件,所以一個(gè)比較簡(jiǎn)單的方法是避免使用ftok,而只是在該頭文件中存放一個(gè)大家都知道的關(guān)鍵字。(d)設(shè)置信號(hào)量的值(PV操作)到這里,讀者

24、肯定有個(gè)疑惑:semop希望改變的semval到底在哪里?我們?cè)趺礇]看到有它的痕跡?其實(shí),前面已經(jīng)說明了,當(dāng)使用semget時(shí),就產(chǎn)生了一個(gè)由內(nèi)核維護(hù)的信號(hào)量集(當(dāng)然每個(gè)信號(hào)量值即semval也是只由內(nèi)核才能看得到了),用戶能看到的就是返回的semid。內(nèi)核通過semop函數(shù)的參數(shù),知道應(yīng)該去改變semid所指向的信號(hào)量的哪個(gè)semval。 (e)對(duì)信號(hào)集實(shí)行控制操作(semval的賦值等)semid是信號(hào)量集合;semnum是信號(hào)在集合中的序號(hào);semum是一個(gè)必須由用戶自定義的結(jié)構(gòu)體,在這里我們務(wù)必弄清楚該結(jié)構(gòu)體的組成: union semunint val; / cmd = SETVAL

25、struct semid_ds *buf / cmd = IPC_SET或者 cmd = IPC_STATushort *array; / cmd = SETALL,或 cmd = GETALL;val只有cmd =SETVAL時(shí)才有用,此時(shí)指定的semval = arg.val。注意:當(dāng)cmd = GETVAL時(shí),semctl函數(shù)返回的值就是我們想要的semval。千萬不要以為指定的semval被返回到arg.val中。array指向一個(gè)數(shù)組,當(dāng)cmd=SETALL時(shí),就根據(jù)arg.array來將信號(hào)量集的所有值都賦值;當(dāng)cmd =GETALL時(shí),就將信號(hào)量集的所有值返回到arg.array

26、指定的數(shù)組中。buf指針只在cmd=IPC_STAT或IPC_SET時(shí)有用,作用是semid所指向的信號(hào)量集(semid_ds機(jī)構(gòu)體)。一般情況下不常用,這里不做談?wù)?。另外,cmd = IPC_RMID還是比較有用的。(f)例碼七信號(hào)量的牛刀小試生產(chǎn)者與消費(fèi)者問題1問題描述:有一個(gè)長(zhǎng)度為N的緩沖池為生產(chǎn)者和消費(fèi)者所共有,只要緩沖池未滿,生產(chǎn)者便可將消息送入緩沖池;只要緩沖池未空,消費(fèi)者便可從緩沖池中取走一個(gè)消息。生產(chǎn)者往緩沖池放信息的時(shí)候,消費(fèi)者不可操作緩沖池,反之亦然。2使用多線程和信號(hào)量解決該經(jīng)典問題的互斥 #include <pthread.h>#include <st

27、dio.h>#include <semaphore.h>#define BUFF_SIZE 10char bufferBUFF_SIZE;char count; / 緩沖池里的信息數(shù)目 sem_t sem_mutex; / 生產(chǎn)者和消費(fèi)者的互斥鎖 sem_t p_sem_mutex; / 空的時(shí)候,對(duì)消費(fèi)者不可進(jìn) sem_t c_sem_mutex; / 滿的時(shí)候,對(duì)生產(chǎn)者不可進(jìn)void * Producer()while(1)sem_wait(&p_sem_mutex); /當(dāng)緩沖池未滿時(shí) sem_wait(&sem_mutex); /等待緩沖池空閑 count+;sem_post(&sem_mutex);if(count < BUFF_SIZE)/緩沖池未滿sem_post(&p_sem_mutex);if(count > 0) /緩沖池

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論