1. Linux線程的發(fā)展
早在LINUX2.2內(nèi)核中。并不存在真正意義上的線程,當(dāng)時Linux中常用的線程pthread實際上是通過進程來模擬的,也就是同過 fork來創(chuàng)建“輕”進程,并且這種輕進程的線程也有個數(shù)的限制:最多只能有4096和此類線程同時運行。 2.4內(nèi)核消除了個數(shù)上的限制,并且允許在系統(tǒng)運行中動態(tài)的調(diào)整進程數(shù)的上限,當(dāng)時采用的是Linux Thread 線程庫,它對應(yīng)的線程模型是“一對一”,而線程的管理是在內(nèi)核為的函數(shù)庫中實現(xiàn),這種線程得到了廣泛的應(yīng)用。但是它不與POSIX兼容。另外還有許多諸如 信號處理,進程ID等方面的問題沒有完全解決。 相似新的2.6內(nèi)核中,進程調(diào)度通過重新的編寫,刪除了以前版本中的效率不高的算法,內(nèi)核框架頁也被重新編寫。開始使用NPTL(Native POSIX Thread Library)線程庫,這個線程庫有以下幾個目標: POSIX兼容,都處理結(jié)果和應(yīng)用,底啟動開銷,低鏈接開銷,與Linux Thread應(yīng)用的二進制兼容,軟硬件的可擴展能力,與C++集 成等。 這一切是2.6的內(nèi)核多線程機制更加完備。 2. Linux 線程的實現(xiàn) Linux線程的基本操作 這里主要講的線程以及相關(guān)操作都是用戶空間的線程操作,在Linux中,一般pthread線程庫是一套通用的線程庫,是由POSIX提出的, 因此具有很好的可移植性。 2.1 線程的創(chuàng)建: 創(chuàng)建線程通常使用的函數(shù)是pthread_create. 2.2 線程的退出: 1) 在線程創(chuàng)建以后,就開始運行相關(guān)的線程函數(shù),在該函數(shù)運行完之后,該線程也就退出了。這是線程退出的一種方法: 運行完畢,自動退出; 2) 調(diào)用pthread_exit函數(shù)主動退出; 3) 進程終止函數(shù)exit函數(shù),一旦結(jié)束了進程,那么此進程中所有線程都將無條件終止。 一個注意點:在默認線程屬性下,如果一個進程有很多線程在同時運行,一個線程在退出以后,當(dāng)前線程所占用的資源并不會隨著線程的終止而得到釋 放。因為所有處在一個進程中的線程共享資源。 線程中還有一個常用函數(shù):pthread_join函數(shù)可以用于將當(dāng)前線程掛起,等待其他線程結(jié)束。實際上,這個函數(shù)是就是一個線程阻塞函數(shù), 調(diào)用它的函數(shù)將一直等待到被等待的線程結(jié)束為止。當(dāng)函數(shù)返回時,被等待線程的資源就被回收。
取消一個線程 有時候,我們想讓一個線程 能夠請求另外一個線程結(jié)束,就像給它發(fā)送一個信號似的。用線程程是可以完成這一操作的,而與單處理經(jīng),線程在被要求結(jié)束執(zhí)行的時候還有一種改變其行為的辦 法。 我們來看看要求一個線程結(jié)束執(zhí)行的函數(shù) 這個定義很明白,給定一個線程標識符,我們就能要求取消它。但在取消線形程請求的接收端,事情會稍微復(fù)雜一些,好在也不是太復(fù)雜。線形程可以用 pthread_setcancelstate設(shè)置自己的取消狀態(tài),下面是這個函數(shù)的定義: 如果取消請求被接受了,線程會進入第二個控制層次----用pthread_setcanceltype設(shè)置取消類型。稍微注意一點就是在android-ndk-r3 里是不支持int pthread_cancel(pthread_t thread); 所以想強制退出線程似乎沒有更好的辦法。 ================================================================================= linux多線程pthread的函數(shù)聲明在中,因此在使用該函數(shù)時,需要把該頭文件引入。 線程的創(chuàng)建 1、創(chuàng)建 int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(* func) (void *), void *restrict arg ); attr: 線程屬性包括:優(yōu)先級、初始棧大小,是否應(yīng)該成為一個守護線程。 缺省設(shè)置,NULL tidp是要創(chuàng)建的線程,創(chuàng)建成功后tipd為先線程的id void *(* func) (void *)是一個函數(shù)指針,該函數(shù)指針的類型為void* (*)(void *) 是一個參數(shù)為void *,返回值也為void *的函數(shù)類型。它的一個簡單的例子如下 void *thread_handler(void *arg) { return NULL; } void *restrict arg 中的arg是void *(* func) (void *)函數(shù)指針的參數(shù)。 補充:函數(shù)聲明中多次出現(xiàn)了restrict,其實這是用于CPU對函數(shù)的優(yōu)化使用的,restrict的使用,由程序員保證使用 restrict標志的參數(shù)間不會有內(nèi)存重疊。 獲取線程自身的id pthread_t pthread_self(void); 等待給定線程終止 int pthread_join( pthread_t tid, void **status); statues返回等待線程的返回值 單個線程有三種退出方式 1.線程從啟動例程中返回(return方式),返回值是現(xiàn)成的退出碼 2.線程被同一進程內(nèi)的其他線程取消 3.線程調(diào)用pthread_exit退出。void pthread_exit(void *rval_ptr) 線程清理處理程序 void pthread_clean_push(void (*rtn)(void *),void *arg) void pthread_clean_pop(iny excute) 清理函數(shù)rtn的調(diào)用順序是由pthread_clean_push函數(shù)安排的。 它在下列幾種情況下執(zhí)行: 1.調(diào)用pthread_exit時 2.響應(yīng)取消請求時 3.用非零execute參數(shù)調(diào)用pthread_clean_pop時 如果execute參數(shù)為0,清理函數(shù)將不被調(diào)用。無論何種情況,pthread_clean_pop都將刪除上次 pthread_clean_push建立的清理處理程序。 如果線程使用return從例程返回,那么pthread_clean_push建立的清理處理程序不會被執(zhí)行。 linux thread與fork的對比 |
|
來自: angelbrian > 《囧~Linux》