在傳統(tǒng)的UNIX進(jìn)程模型中,每個(gè)進(jìn)程只有一個(gè)控制線(xiàn)程。從概念上講,這與基于線(xiàn)程的模型中只包含一個(gè)線(xiàn)程是相同的。在POSIX線(xiàn)程(pthread)的情況下,程序開(kāi)始運(yùn)行時(shí),它也是以單進(jìn)程中的單個(gè)控制線(xiàn)程啟動(dòng)的,在創(chuàng)建多個(gè)控制線(xiàn)程以前,程序的行為與傳統(tǒng)的進(jìn)程并沒(méi)有什么區(qū)別。新增的線(xiàn)程可以通過(guò)調(diào)用pthread_create函數(shù)創(chuàng)建。
#include <pthread.h>int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);返回值:若成功則返回0,否則返回錯(cuò)誤編號(hào)
當(dāng)pthread_create成功返回時(shí),由tidp指向的內(nèi)存單元被設(shè)置為新創(chuàng)建的線(xiàn)程的線(xiàn)程ID。attr參數(shù)用于定制各種不同的線(xiàn)程屬性。線(xiàn)程屬性在以后介紹,眼下暫時(shí)把它設(shè)置為NULL,創(chuàng)建默認(rèn)屬性的線(xiàn)程。
新創(chuàng)建的線(xiàn)程從start_rtn函數(shù)的地址開(kāi)始運(yùn)行,該函數(shù)只有一個(gè)無(wú)類(lèi)型指針參數(shù)arg,如果需要向start_rtn函數(shù)傳遞的參數(shù)不止一個(gè),那么需要把這些參數(shù)放到一個(gè)結(jié)構(gòu)中,然后把這個(gè)結(jié)構(gòu)的地址作為arg參數(shù)傳入。
線(xiàn)程創(chuàng)建時(shí)并不能保證哪個(gè)線(xiàn)程會(huì)先運(yùn)行:是新創(chuàng)建的線(xiàn)程還是調(diào)用線(xiàn)程。新創(chuàng)建的線(xiàn)程可以訪問(wèn)進(jìn)程的地址空間,并且繼承調(diào)用線(xiàn)程的浮點(diǎn)環(huán)境和信號(hào)屏蔽字,但是該線(xiàn)程的未決信號(hào)集被清除。
注意pthread函數(shù)在調(diào)用失敗時(shí)通常會(huì)返回錯(cuò)誤碼,它們并不像其他的POSIX函數(shù)一樣設(shè)置errno。每個(gè)線(xiàn)程都提供errno的副本,這只是為了與使用errno的現(xiàn)有函數(shù)兼容。在線(xiàn)程中,從函數(shù)中返回錯(cuò)誤碼更為清晰整潔,不需要依賴(lài)那些隨著函數(shù)執(zhí)行不斷變化的全局狀態(tài),因而可以把錯(cuò)誤的范圍限制在引起出錯(cuò)的函數(shù)中。
實(shí)例
雖然沒(méi)有可移植的方法打印線(xiàn)程ID,但是可以寫(xiě)一個(gè)小的測(cè)試程序來(lái)完成這個(gè)任務(wù),以便更深入地了解線(xiàn)程是如何工作的。程序清單11-1中創(chuàng)建了一個(gè)線(xiàn)程并且打印進(jìn)程ID、新線(xiàn)程的線(xiàn)程ID以及初始線(xiàn)程的線(xiàn)程ID。
程序清單11-1 打印線(xiàn)程ID
#include "apue.h"#include <pthread.h>pthread_t ntid;void PRintids(const char *s){ pid_t pid; pthread_t tid; pid = getpid(); tid = pthread_self(); printf("%s pid %u tid %u (0x%x) /n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);}void *thr_fn(void *arg){ printids("new thread : "); return((void *)0);}intmain(void){ int err; err = pthread_create(&ntid, NULL, thr_fn, NULL); if(err != 0) err_quit("can't create thread: %s/n", strerror(err)); printids("main thread: "); sleep(1); exit(0);}
編譯上面程序過(guò)程中遇到了undefined reference to ‘pthread_create’的問(wèn)題:
首先,檢查了函數(shù)名,沒(méi)有寫(xiě)錯(cuò);然后檢查了頭文件<pthread.h>,也包含了。這種摸不著頭腦的問(wèn)題總是讓人很糾結(jié)的......最終在網(wǎng)上找到了出現(xiàn)該問(wèn)題的原因及其解決方案,參考自:http://blog.csdn.net/llqkk/article/details/2854558
問(wèn)題原因: pthread 庫(kù)不是 linux 系統(tǒng)默認(rèn)的庫(kù),連接時(shí)需要使用靜態(tài)庫(kù) libpthread.a,所以在使用pthread_create()創(chuàng)建線(xiàn)程,以及調(diào)用 pthread_atfork()函數(shù)建立fork處理程序時(shí),需要鏈接該庫(kù)。 解決方案: 在編譯中要加 -lpthread參數(shù)
問(wèn)題解決了就OK了嗎?當(dāng)然不行,由此問(wèn)題恰好暴露了之前學(xué)過(guò)的一些知識(shí)其實(shí)并沒(méi)有真正吃透,學(xué)的時(shí)候理解,遇到問(wèn)題的時(shí)候卻想不起來(lái)。其實(shí)上面出現(xiàn)的這個(gè)問(wèn)題牽涉到了之前學(xué)過(guò)的如下兩個(gè)知識(shí)點(diǎn):
(1)軟件開(kāi)發(fā)工具GCC http://www.CUOXin.com/nufangrensheng/p/3426405.html。注意其中的GCC鏈接選項(xiàng)部分。
(2)UNIX標(biāo)準(zhǔn)化及實(shí)現(xiàn)之POSIX標(biāo)準(zhǔn)可選頭文件 http://www.CUOXin.com/nufangrensheng/p/3496116.html。從中可以看到pthread.h是POSIX標(biāo)準(zhǔn)的可選頭文件,也就是說(shuō)pthread庫(kù)不是Linux系統(tǒng)默認(rèn)的庫(kù),鏈接時(shí)需要使用靜態(tài)庫(kù)libpthread.a。
更多關(guān)于undefined reference to...的問(wèn)題可參考:http://ticktick.blog.51cto.com/823160/431329
現(xiàn)在我們言歸正傳,從程序清單11-1運(yùn)行結(jié)果來(lái)看,兩個(gè)線(xiàn)程的進(jìn)程ID相同,但線(xiàn)程ID不同。不過(guò)這不是絕對(duì)的,依賴(lài)于具體的實(shí)現(xiàn)。
這個(gè)實(shí)例有兩個(gè)需要注意的地方:
(1)需要處理主線(xiàn)程和新線(xiàn)程之間的競(jìng)爭(zhēng)。首先是主線(xiàn)程需要休眠,如果主線(xiàn)程不休眠,它就可能退出,這樣在新線(xiàn)程有機(jī)會(huì)運(yùn)行之前整個(gè)進(jìn)程可能就已經(jīng)終止了。這種行為特征依賴(lài)于操作系統(tǒng)中的線(xiàn)程實(shí)現(xiàn)和調(diào)度算法。
(2)新線(xiàn)程是通過(guò)調(diào)用pthread_self函數(shù)獲取自己的線(xiàn)程ID,而不是從共享內(nèi)存中讀出或者從線(xiàn)程的啟動(dòng)例程中以參數(shù)的形式接收到。回憶pthread_create函數(shù),它會(huì)通過(guò)第一個(gè)參數(shù)(tidp)返回新建線(xiàn)程的線(xiàn)程ID。在本例中,主線(xiàn)程把新線(xiàn)程ID存放在ntid中,但是新建的線(xiàn)程并不能安全地使用它,如果新線(xiàn)程在主線(xiàn)程調(diào)用pthread_create返回之前就運(yùn)行了,那么新線(xiàn)程看到的是未經(jīng)初始化的ntid的內(nèi)容,這個(gè)內(nèi)容并不是正確的線(xiàn)程ID。
本篇博文內(nèi)容摘自《UNIX環(huán)境高級(jí)編程》(第二版),僅作個(gè)人學(xué)習(xí)記錄所用。關(guān)于本書(shū)可參考:http://www.apuebook.com/。
|
新聞熱點(diǎn)
疑難解答
圖片精選