天河做網(wǎng)站開發(fā)外包公司和勞務(wù)派遣
目錄
一、什么是線程分離
1.1pthread_detach
?1.2pthread線程庫存在的意義
1.3__thread線程的局部存儲
1.4系統(tǒng)調(diào)用clone
一、什么是線程分離
1.1pthread_detach
int pthread_detach(pthread_t thread);
pthread_detach(pthread_self());//對自己進行分離
而為什么要有線程分離或者是為什么要將線程進行分離呢?我們在運行或者打開一個軟件或應(yīng)用時,往往我們不去主動關(guān)閉,該線程一般是不會主動進行退出的,所以一般情況下主線程都是常駐的而在我們需要去進行其他操作時再由主線程去創(chuàng)建其他新線程,所以主線程一般都是死循環(huán)運行的。而一般情況下我們都希望主線程是最后一個退出的。
所以線程分離底層依舊屬于同一個進程,只是不需要進行等待了。
?1.2pthread線程庫存在的意義
Linux中不存在真正的線程,線程底層都是用進程來進行模擬的,而之所以有線程是針對面向用戶進行使用的,而Linux中的線程也被叫做用戶級線程,所以在Linux中存在著一個線程庫,庫中則封裝著由OS將線程轉(zhuǎn)換成輕量級進程的具體方法。所以就要由OS提供一個庫將線程進行封裝,然后轉(zhuǎn)換成用戶習(xí)慣的使用方式為用戶提供用戶習(xí)慣的上層接口。
所以我們之前使用的pthread_t類型所表示的數(shù)字是什么呢?
我們可以在編寫代碼時,讓代碼拿到當前線程tid然后轉(zhuǎn)換成16進制。
也可以通過指令去獲取指定進程的LWP。
?但是通過觀察可以發(fā)現(xiàn),我們獲取的tid和LWP并不一樣。
而OS在代碼剛開始運行時,首先創(chuàng)建的是一個進程,包括task_struct 、mm_struct 、頁表。然后將磁盤中存儲的代碼加載到內(nèi)存中然后進行運行。而我們在代碼中創(chuàng)建線程,但系統(tǒng)中并沒有線程的概念,只有輕量級進程的概念,但是又需要讓用戶看到并對線程進行操作,所以線程的創(chuàng)建管理等工作是在庫中進行實現(xiàn)的,庫中對各種操作進行了封裝處理。而庫也是一個文件存在于OS中
?而這個庫就是一個動態(tài)庫,而想要執(zhí)行該庫就需要先將其加載到內(nèi)存中,然后將其映射到該進程的地址空間的共享區(qū)中,所以創(chuàng)建線程、等待線程、終止線程等等工作都是在庫中進行實現(xiàn)的,所以庫就要對用戶創(chuàng)建的線程進行管理,而管理的方式一如既往是先描述,再組織。
而動態(tài)庫就會如下圖的方式一樣被加載到進程的地址空間中,而線程也有自己的線程控制塊TCB,而一般操作系統(tǒng)是不直接提供TCB數(shù)據(jù)結(jié)構(gòu)的。
?所以創(chuàng)建一個線程就創(chuàng)建一個tcb,而每個tcb的起始地址就叫做線程的tid,所以系統(tǒng)提供給用戶的線程的地址就是tcb的起始地址,通過該地址就能找到線程的所有屬性信息。而tcb中就封裝了該線程的LWP等信息。而庫中不僅維護該線程所獨立擁有的棧等,還會維護相關(guān)的數(shù)據(jù)結(jié)構(gòu)。而線程的棧結(jié)構(gòu)和上下文數(shù)據(jù)都是自己私有的。主線程的棧就在如圖所示的地方,一旦開辟新的線程就會創(chuàng)建和分配新的棧結(jié)構(gòu),所以每個線程都有獨立的棧結(jié)構(gòu)。雖然線程間的棧結(jié)構(gòu)是獨立的,但其指向的都是同一進程的同一地址空間,所以彼此之間還是能夠相互訪問的。
這個庫是一個動態(tài)庫,也被叫做共享庫,共享庫可以通過頁表被映射到每一個進程地址空間當中,所以不僅僅是一個進程,整個系統(tǒng)的所有進程中的線程,都由該庫進行統(tǒng)一管理。
1.3__thread線程的局部存儲
假設(shè)定義了一個全局變量int gvl;
__thread int gvl;
則可以對gvl的全局屬性做修改,讓它變成每個線程所私有的
全局變量一般存在于進程地址空間的初始化數(shù)據(jù)區(qū),是所有線程所共享的,也就是說一個線程對其進行修改,所有的線程都能看到。如果這時在定義全局變量之前加上__thread就可以讓該全局變量變成每個線程所私有的,從而不會受其他線程的影響。而這就叫做線程的局部存儲。在代碼編譯時OS會將該變量單獨拆解出來,存放到每一個線程的局部存儲當中。注意,局部存儲只可以存儲內(nèi)置類型,不能存儲自定義類型。
1.4系統(tǒng)調(diào)用clone
在代碼執(zhí)行過程中,pcb在執(zhí)行線程相關(guān)的代碼時,也需要找到線程所對應(yīng)的棧的位置,clone就可以解決這個問題,而clone就是pthread_create的底層實現(xiàn)。