多核技術(shù)5linux多線程編程_第1頁(yè)
多核技術(shù)5linux多線程編程_第2頁(yè)
多核技術(shù)5linux多線程編程_第3頁(yè)
多核技術(shù)5linux多線程編程_第4頁(yè)
多核技術(shù)5linux多線程編程_第5頁(yè)
已閱讀5頁(yè),還剩59頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、1多核程序設(shè)計(jì)2第五章 Linux多線程編程1 POSIX線程庫(kù)介紹2 Pthreads庫(kù)的基本操作3 線程的屬性4 線程互斥與同步5 使用GDB調(diào)試線程35.1 線程庫(kù)簡(jiǎn)介POSIX 線程庫(kù)Pthreads介紹IEEE POSIX 標(biāo)準(zhǔn) p1003.1c (Pthreads) 定義了處理線程的一系列C語(yǔ)言類型的API。在Linux中,線程一般被認(rèn)為是“輕量級(jí)的進(jìn)程”。Linux 創(chuàng)建進(jìn)程所使用的函數(shù)是fork()或者vfork()。而對(duì)線程的創(chuàng)建和管理Linux可以使用POSIX的線程庫(kù)pthreads提供的APIs。4POSIX簡(jiǎn)介:Portable Operating System In

2、terface可移植操作系統(tǒng)接口縮寫(xiě)為 POSIX 是為了讀音更像 UNIX。POSIX 標(biāo)準(zhǔn)是由IEEE(Institute of Electrical and Electronics Engineers,電氣和電子工程師協(xié)會(huì))開(kāi)發(fā) ,是由ANSI(American National Standards Institute,美國(guó)國(guó)家標(biāo)準(zhǔn)學(xué)會(huì) )和ISO(International Organization for Standardization,國(guó)際標(biāo)準(zhǔn)化組織 )標(biāo)準(zhǔn)化。5POSIX的誕生和Unix的發(fā)展是密不可分的由于各廠家對(duì)Unix的開(kāi)發(fā)各自為政,造成了Unix的版本相當(dāng)混亂,給軟件的可

3、移植性帶來(lái)很大困難,對(duì)Unix的發(fā)展極為不利。為結(jié)束這種局面,IEEE開(kāi)發(fā)了POSIX,它在源代碼級(jí)別上定義了一組最小的Unix(類Unix)操作系統(tǒng)接口。POSIX并不局限于UNIX。許多其它的操作系統(tǒng),例如DEC OpenVMS 和 Microsoft Windows NT,Linux等都支持(部分) POSIX標(biāo)準(zhǔn)6Pthread線程庫(kù)簡(jiǎn)介:POSIX 1003.1c定義了處理線程的一系列C語(yǔ)言類型的API函數(shù),提供了一個(gè)可移植的多線程庫(kù),稱為Pthreads。Pthreads現(xiàn)在已成為L(zhǎng)inux操作系統(tǒng)中多線程接口的標(biāo)準(zhǔn),并且廣泛使用在大多數(shù)的unix平臺(tái)上。針對(duì)Windows操作系統(tǒng)

4、,Pthreads也存在一個(gè)開(kāi)放源代碼的版本,稱為pthreads-win32。如果打算使用C語(yǔ)言開(kāi)發(fā)多線程程序,并且需要一個(gè)能比OpenMP提供更多直接控制的可移植的API,那么Pthreads是一個(gè)很好的選擇。7POSIX API沒(méi)有限定線程應(yīng)該如何工作,因此對(duì)于如何去編制線程程序就留有了很大的余地。Pthread本來(lái)是一套用戶級(jí)線程庫(kù),但在Linux上實(shí)現(xiàn)時(shí),卻使用了內(nèi)核級(jí)線程來(lái)完成,這樣的好處是,可以充分的提高程序的并發(fā)性。Pthreads庫(kù)的函數(shù)原形定義在中,編寫(xiě)多線程程序時(shí)需要include該頭文件。編譯時(shí)需要鏈接libpthread庫(kù)(-lpthread)8Pthread線程庫(kù)提

5、供的函數(shù)一般都以pthread開(kāi)頭,例如:前綴功能集合pthread_線程或子線程pthread_attr_線程對(duì)象屬性pthread_mutex_互斥量pthread_mutexattr_互斥量對(duì)象屬性pthread_cond_條件變量pthread_condattr_條件變量屬性9使用fork()創(chuàng)建進(jìn)程和使用POSIX線程庫(kù)差別:使用fork()創(chuàng)建進(jìn)程的特點(diǎn):代價(jià)昂貴,通常子進(jìn)程需要拷貝父進(jìn)程的整個(gè)上下文,比如數(shù)據(jù)等。進(jìn)程間的通信方式比較復(fù)雜,比如使用管道、消息、共享內(nèi)存等方法。操作系統(tǒng)在實(shí)現(xiàn)進(jìn)程間的切換比線程切換更費(fèi)時(shí)。使用POSIX pthreads庫(kù)創(chuàng)建線程的特點(diǎn):線程可使用存在

6、于進(jìn)程中的資源,因此創(chuàng)建線程比創(chuàng)建進(jìn)程更快。線程間的通信方式更容易,比如通過(guò)進(jìn)程中的變量,可以讓多個(gè)線程共享數(shù)據(jù)。操作系統(tǒng)對(duì)線程切換比對(duì)進(jìn)程切換更容易和快速。105.2 基本線程操作獲得當(dāng)前線程標(biāo)志每個(gè)線程都有一個(gè)標(biāo)識(shí),是pthread_t類型的。使用pthread_self ( )函數(shù)可以獲得當(dāng)前線程的標(biāo)志,函數(shù)返回值就是當(dāng)前線程的標(biāo)志。 pthread_t pthread_self (void);由于pthread_t可能是一個(gè)數(shù)據(jù)結(jié)構(gòu),因此POSIX提供了一個(gè)函數(shù)pthread_equal()來(lái)比較兩個(gè)線程標(biāo)識(shí)是否相等。 11線程的創(chuàng)建pthreads 線程庫(kù)中提供的創(chuàng)建線程的函數(shù)是pt

7、hread_create():#include int pthread_create( pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);12線程的退出 在線程的處理函數(shù)中,可以顯示的調(diào)用pthread_exit()結(jié)束線程執(zhí)行,也可以不調(diào)用pthread_exit(),而只是讓線程處理程序返回。 void pthread_exit(void * retval) (清理函數(shù))除了pthread_exit() 函數(shù),可以讓當(dāng)前調(diào)用pthread_exit() 的線程顯示地退

8、出外,線程也可以使用 pthread_cancel() 函數(shù)終止其他線程的執(zhí)行。13等待線程結(jié)束pthread_join( ) 函數(shù)會(huì)掛起創(chuàng)建線程的線程的執(zhí)行,直到等待到想要等待的子線程,并釋放子線程的資源,若成功返回0,否則返回錯(cuò)誤編號(hào),thread_return或者是子線程pthread_exit返回的參數(shù),或者是PTHREAD_CANCELED。 int pthread_join(pthread_t th, void *thread_return);等待的線程必須在可加入的狀態(tài),即沒(méi)有對(duì)線程調(diào)用pthread_detach()函數(shù),或者創(chuàng)建線程時(shí)把其屬性設(shè)置為PTHREAD_CREATE

9、_DETACHED。一個(gè)子線程不能被兩個(gè)線程等待。14線程的分離主線程創(chuàng)建子線程,且子線程本身自己有自我回收內(nèi)存資源的能力。 int pthread_detach(pthread_t th);讓線程可以處于分離(detached)狀態(tài),當(dāng)線程處于這種狀態(tài)的時(shí)候,線程不需要其它線程等待其結(jié)束,處于分離狀態(tài)的線程有能力在自己結(jié)束執(zhí)行的時(shí)候回收相關(guān)的內(nèi)存資源。如果線程處于分離狀態(tài)(兩種方式),使用pthread_join()函數(shù)的時(shí)候會(huì)返回錯(cuò)誤。15使用Pthreads的程序?qū)嵗?include #include #include #include #define THREAD_NUMBER 2in

10、t retval_hello1= 2, retval_hello2 = 3;void* hello1(void *arg) char *hello_str = (char *)arg; sleep(1); printf(%sn, hello_str); pthread_exit(&retval_hello1);void* hello2(void *arg) char *hello_str = (char *)arg; sleep(2); printf(%sn, hello_str); pthread_exit(&retval_hello2);16int main(int argc, char

11、*argv) int i; int ret_val; int *retval_hello2; pthread_t ptTHREAD_NUMBER; const char *argTHREAD_NUMBER; arg0 = hello world from thread1; arg1 = hello world from thread2; printf(Begin to create threads.n); ret_val = pthread_create(&pt0, NULL, hello1, (void *)arg0); if (ret_val != 0 ) printf(pthread_c

12、reate error!n); exit(1);17 ret_val = pthread_create(&pt1, NULL, hello2, (void *)arg1); if (ret_val != 0 ) printf(pthread_create error!n); exit(1); printf(Begin to wait for threads.n); for(i = 0; i THREAD_NUMBER; i+) ret_val = pthread_join(pti, (void *)&retval_helloi); if (ret_val != 0) printf(pthrea

13、d_join error!n); exit(1); else printf(return value is %dn, *retval_helloi); printf(Now, the main thread returns.n); return 0; 183 線程的屬性屬性名含義detachstate選擇被創(chuàng)建的線程是處于可加入的狀態(tài)還是分離狀態(tài)。 可加入狀態(tài)值是PTHREAD_CREATE_JOINABLE; 分離狀態(tài)值是PTHREAD_CREATE_DETACHED; 缺省狀態(tài)值是PTHREAD_CREATE_JOINABLE。 pthread_attr_setdetachstate()

14、可設(shè)置線程為加入或者分離狀態(tài); pthread_attr_getdetachstate() 可以獲得當(dāng)前線程是否是加入的或者是分離的狀態(tài)。 schedpolicy為被創(chuàng)建的線程選擇調(diào)度策略。被創(chuàng)建的線程的狀態(tài)可以是SCHED_OTHER(一般的,非實(shí)時(shí)調(diào)度)、SCHED_RR (實(shí)時(shí),輪轉(zhuǎn)調(diào)度) 或者SCHED_FIFO(實(shí)時(shí),先進(jìn)先出調(diào)度)。缺省值是SCHED_OTHER。實(shí)時(shí)調(diào)度SCHED_RR 和 SCHED_FIFO 只能用于有超級(jí)用戶權(quán)限的進(jìn)程使用。 pthread_attr_setschedpolicy() 和 pthread_attr_getschedpolicy() 函數(shù)可以設(shè)

15、置和獲得線程的調(diào)度屬性。19屬性名含義 schedparam為被創(chuàng)建的線程選擇調(diào)度參數(shù)。這里的調(diào)度參數(shù)指的是線程的調(diào)度優(yōu)先級(jí)。缺省優(yōu)先級(jí)是 0 。這個(gè)屬性對(duì)于 SCHED_OTHER 是不重要的;它只對(duì)SCHED_RR 和 SCHED_FIFO 兩個(gè)和實(shí)時(shí)調(diào)度相關(guān)的調(diào)度方式有效。 pthread_attr_setschedparam() 和 pthread_attr_getschedparam() 兩個(gè)函數(shù)可以分別對(duì)線程的優(yōu)先級(jí)進(jìn)行設(shè)置和獲取。 inheritsched選擇對(duì)新創(chuàng)建的線程的調(diào)度策略和調(diào)度參數(shù)是否被schedpolicy 和schedparam 屬性決定(這時(shí)的值是PTHREAD

16、_EXPLICIT_SCHED)或者是通過(guò)父線程繼承而得到的(這時(shí)的值是PTHREAD_INHERIT_SCHED)。缺省的值是PTHREAD_EXPLICIT_SCHED。 scope為選擇被創(chuàng)建的線程調(diào)度競(jìng)爭(zhēng)范圍。缺省值是PTHREAD_SCOPE_SYSTEM,表示線程和系統(tǒng)的所有的其他運(yùn)行在CPU上的進(jìn)程爭(zhēng)奪CPU 資源。如果是PTHREAD_SCOPE_PROCESS,表示調(diào)度的競(jìng)爭(zhēng)只發(fā)生在運(yùn)行于同一進(jìn)程空間的線程之間,線程的優(yōu)先級(jí)只在同一進(jìn)程空間的線程之間有效,和其他進(jìn)程無(wú)關(guān)。20設(shè)置線程屬性的程序?qū)嵗?include #include #include void* sum_val

17、(void *arg) int sum = 0; int i; int count = *(int *)arg; for (i = 0; i count; i+) sum = sum + i; printf(sum is %dn, sum); pthread_exit(0);21int main(int argc, char *argv) pthread_t pt; int count = 10; int ret_val; pthread_attr_t attr; struct sched_param sp; sp._sched_priority = 2; /線程屬性初始化 ret_val =

18、 pthread_attr_init(&attr); if (ret_val != 0) printf(pthread_attr_init error!n); exit(1); /線程狀態(tài)設(shè)置為PTHREAD_CREATE_DETACHED ret_val =pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); if (ret_val != 0) printf(pthread_attr_setdetachstate error!n); exit(1); 22 /線程調(diào)度方式被設(shè)置為輪轉(zhuǎn)法 ret_val = pthread_at

19、tr_setschedpolicy(&attr, SCHED_RR); if (ret_val != 0) printf(pthread_attr_setschedpolicy error!n); exit(1); /線程調(diào)度優(yōu)先級(jí)設(shè)置為2,默認(rèn)值是0 ret_val = pthread_attr_setschedparam(&attr, &sp); if (ret_val != 0) printf(pthread_attr_setschedparam error!n); exit(1); /設(shè)置新創(chuàng)建線程的調(diào)度策略和調(diào)度參數(shù)是否被上述兩個(gè)屬性所決定 ret_val = pthread_att

20、r_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); if (ret_val != 0) printf(pthread_attr_setinheritsched error!n); exit(1); 23 /設(shè)置線程的調(diào)度競(jìng)爭(zhēng)范圍 ret_val = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); if (ret_val != 0) printf(pthread_attr_setscope error!n); exit(1); /創(chuàng)建線程 ret_val = pthread_create(&p

21、t, NULL, sum_val, (void *)&count); if (ret_val != 0 ) printf(pthread_create error!n); exit(1); /釋放屬性對(duì)象 pthread_attr_destroy(&attr); sleep(5); return 0;244 線程互斥和同步線程間的互斥操作可以使用Mutex來(lái)實(shí)現(xiàn),用來(lái)保護(hù)并發(fā)讀寫(xiě)操作中共享的數(shù)據(jù)結(jié)構(gòu)。POSIX 線程庫(kù)對(duì)mutex提供了以下函數(shù)進(jìn)行操作: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr

22、_t *mutexattr); int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_destroy(pthread_mutex_t *mutex);25線程互斥和同步MutexMutex具有如下特性:原子性。對(duì)mutex的加鎖和解鎖操作是原子的,一個(gè)線程進(jìn)行 mutex 操作的過(guò)程中,其他線程不能對(duì)同一個(gè) mutex

23、 進(jìn)行其他操作。單一性。擁有mutex的線程除非釋放mutex,否則其他線程不能擁有此mutex。非忙等待。等待mutex的線程處于等待狀態(tài),直到要等待的mutex處于未加鎖狀態(tài),這時(shí)操作系統(tǒng)負(fù)責(zé)喚醒等待此mutex的線程。26線程互斥和同步MutexMutex的三種類型:快速(fast)mutex,這種類型也是默認(rèn)的類型。遞歸(recursive)mutex。同一線程多次給互斥量上鎖,那么系統(tǒng)將會(huì)知道該上鎖行為來(lái)自同一線程,那么就會(huì)同意線程給該互斥量上鎖。錯(cuò)誤檢查(error checking) mutex 。如果該互斥量已經(jīng)被上鎖,那么后續(xù)的上鎖將會(huì)失敗而不會(huì)阻塞,操作將會(huì)返回EDEADL

24、K。27Mutex相關(guān)函數(shù)創(chuàng)建與初始化:有兩種方法創(chuàng)建互斥鎖,靜態(tài)方式和動(dòng)態(tài)方式。動(dòng)態(tài)創(chuàng)建與初始化: pthread_mutex_t mutex pthread_mutexattr_t attr pthread_mutex_init (&mutex, &attr) PTHREAD_MUTEX_TIMED_NP是缺省值,就是普通的快速鎖。 PTHREAD_MUTEX_RECURSIVE_NP是遞歸鎖。 PTHREAD_MUTEX_ERRORCHECK_NP是錯(cuò)誤檢查鎖。28Mutex相關(guān)函數(shù)靜態(tài)創(chuàng)建與初始化: pthread_mutex_t fastmutex = PTHREAD_MUTEX_I

25、NITIALIZER; pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; pthread_mutex_t errchmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;29Mutex相關(guān)函數(shù)銷毀: pthread_mutex_destroy (&mutex) 30Mutex相關(guān)函數(shù)加解鎖操作: pthread_mutex_lock (&mutex); pthread_mutex_trylock (&mutex); pthread_mutex_unlock (&mute

26、x); 函數(shù)pthread_mutex_trylock ( )的語(yǔ)義與函數(shù)pthread_mutex_lock ( )類似,不同的是在鎖已經(jīng)被占據(jù)時(shí)返回EBUSY而不是掛起等待。31Thread AThread Bpthread_mutex_lock (&mutex1);pthread_mutex_lock (&mutex2);pthread_mutex_lock (&mutex2);pthread_mutex_lock (&mutex1);pthread_mutex_lock (&mutex1);f (x);pthread_mutex_lock (&mutex1);32線程互斥和同步Mute

27、x程序?qū)嵗?Mutex的使用。 count.c線程使用mutex的簡(jiǎn)單代碼如下:pthread_mutex_t mylock;mylock= PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock(&mylock);/*.*/pthread_mutex_unlock(&mylock);36線程互斥和同步條件變量 條件變量是線程的同步設(shè)備。在線程間使用條件變量可以使得一個(gè)線程在執(zhí)行過(guò)程中,因滿足某個(gè)條件而發(fā)出信號(hào)通知另一個(gè)線程;而另一個(gè)線程可以處于掛起狀態(tài),等待某個(gè)條件的滿足后,才繼續(xù)執(zhí)行。37線程互斥和同步條件變量條件變量必須和mutex一起使用來(lái)避免競(jìng)爭(zhēng)情況

28、,相關(guān)的操作函數(shù)如下:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);int pthread_cond_signal (pthread_cond_t *cond);int pthread_cond_broadcast (pthread_cond_t *cond);int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);i

29、nt pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);int pthread_cond_destroy (pthread_cond_t *cond);38線程互斥和同步條件變量程序?qū)嵗龡l件變量的使用。 threadcon.c threadcontime.c45線程的撤銷一個(gè)線程可以通過(guò)向另個(gè)線程發(fā)送“請(qǐng)求”來(lái)結(jié)束另一個(gè)線程的執(zhí)行。 pthread_cancel (pthread_t)接受撤銷線程可以根據(jù)線程的設(shè)置忽略,推遲或者立即結(jié)束自己。

30、撤銷點(diǎn):線程檢測(cè)未處理的撤銷請(qǐng)求,并執(zhí)行撤銷請(qǐng)求的程序執(zhí)行點(diǎn)。46線程的撤銷POSIX pthreads庫(kù)中關(guān)于撤銷操作的函數(shù)有: int pthread_setcancelstate(int state, int *oldstate); state值可以為PTHREAD_CANCEL_ENABLE 或 PTHREAD_CANCEL_DISABLE。int pthread_setcanceltype(int type, int *oldtype); type值可以為PTHREAD_CANCEL_DEFERRED 或 PTHREAD_CANCEL_ASYNCHRONOUSvoid pthread

31、_testcancel(void);47線程的撤銷程序?qū)嵗€程撤銷。 cancel.c threadcancel.c清理實(shí)例程序在撤銷線程的時(shí)候,可以編寫(xiě)程序讓線程進(jìn)一步進(jìn)行所謂的清理工作,例如,如果已經(jīng)擁有了某個(gè)mutex,在清理例程中可以釋放這個(gè)mutex。void my_cleanup(void *arg) pthread_mutex_unlock(pthread_mutex_t *)arg); printf(call mycleanup!n);56POSIX 信號(hào)量POSIX 信號(hào)量在多線程編程中可以起到同步或互斥的作用。用POSIX 信號(hào)量可以實(shí)現(xiàn)傳統(tǒng)操作系統(tǒng)P、V操作。由于POSI

32、X信號(hào)量不是內(nèi)核負(fù)責(zé)維護(hù),所以當(dāng)進(jìn)程退出后,POSIX信號(hào)量自動(dòng)消亡。#include int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_wait(sem_t * sem); int sem_trywait(sem_t * sem); int sem_post(sem_t * sem); int sem_getvalue(sem_t * sem, int * sval); int sem_destroy(sem_t * sem);57POSIX 信號(hào)量sem_init創(chuàng)建一個(gè)信號(hào)量,并初始化其值為value,

33、pshared決定了信號(hào)量能否在幾個(gè)進(jìn)程間共享.由于目前Linux還沒(méi)有實(shí)現(xiàn)進(jìn)程間共享信號(hào)量,所以這個(gè)值只能夠取0。sem_wait調(diào)用將阻塞進(jìn)程,直到信號(hào)量的值大于0。這個(gè)函數(shù)返回的時(shí)候自動(dòng)的將信號(hào)量的值的減一。sem_post和sem_wait相反,是將信號(hào)量的內(nèi)容加一同時(shí)發(fā)出信號(hào)喚醒等待的進(jìn)程。sem_trywait和sem_wait相同,不過(guò)不阻塞的,當(dāng)信號(hào)量的值為0的時(shí)候返回EAGAIN,表示以后重試。58信號(hào)量運(yùn)行原理一個(gè)任務(wù)要想訪問(wèn)共享資源,首先必須得到信號(hào)量,獲取信號(hào)量的操作將把信號(hào)量的值減1,若當(dāng)前信號(hào)量的值為負(fù)數(shù),表明無(wú)法獲得信號(hào)量,該任務(wù)必 須掛起在該信號(hào)量的等待隊(duì)列等待該信號(hào)量可用;若當(dāng)前信號(hào)量的值為非負(fù)數(shù),表示可以獲得信號(hào)量,因而可以立刻訪問(wèn)被該信號(hào)量保護(hù)的共享資源。當(dāng)任務(wù)訪問(wèn)完被信號(hào)量保護(hù)的共享資源后,必須釋放信號(hào)量,釋放信號(hào)量通過(guò)把信號(hào)量的值加1實(shí)現(xiàn),如果信號(hào)量的值為非正數(shù),表明有任務(wù)等待當(dāng)前信號(hào)量,因此它也喚醒所有等待該信號(hào)量的任務(wù)。59信號(hào)量程序?qū)嵗褂肞OSIX信號(hào)量解決簡(jiǎn)單生產(chǎn)者和消費(fèi)者。 prodcons.c

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 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)論