1. Linux線程的發展
早在LINUX2.2核心中。並不存在真正意義上的線程,當時Linux中常用的線程pthread實際上是通過進程來類比的,也就是同過fork來建立“輕”進程,並且這種輕進程的線程也有個數的限制:最多隻能有4096和此類線程同時運行。
2.4核心消除了個數上的限制,並且允許在系統運行中動態調整進程數的上限,當時採用的是Linux Thread 線程庫,它對應的執行緒模式是“一對一”,而線程的管理是在核心為的函數庫中實現,這種線程得到了廣泛的應用。但是它不與POSIX相容。另外還有許多諸如訊號處理,進程ID等方面的問題沒有完全解決。
相似新的2.6核心中,進程調度通過重新的編寫,刪除了以前版本中的效率不高的演算法,核心架構頁也被重新編寫。開始使用NPTL(Native POSIX Thread Library)線程庫,這個線程庫有以下幾個目標: POSIX相容,都處理結果和應用,底啟動開銷,低連結開銷,與Linux Thread應用的二進位相容,軟硬體的可擴充能力,與C++整合等。 這一切是2.6的核心多線程機制更加完備。
2. Linux 線程的實現
Linux線程的基本操作
這裡主要講的線程以及相關操作都是使用者空間的線程操作,在Linux中,一般pthread線程庫是一套通用的線程庫,是由POSIX提出的,因此具有很好的可移植性。
2.1 線程的建立: 建立線程通常使用的函數是pthread_create.
2.2 線程的退出:
1) 線上程建立以後,就開始運行相關的線程函數,在該函數運行完之後,該線程也就退出了。這是線程退出的一種方法: 運行完畢,自動結束;
2) 調用pthread_exit函數主動退出;
3) 進程終止函數exit函數,一旦結束了進程,那麼此進程中所有線程都將無條件終止。
一個注意點:在預設線程屬性下,如果一個進程有很多線程在同時運行,一個線程在退出以後,當前線程所佔用的資源並不會隨著線程的終止而得到釋放。因為所有處在一個進程中的線程共用資源。
線程中還有一個常用函數:pthread_join函數可以用於將當前線程掛起,等待其他線程結束。實際上,這個函數是就是一個線程阻塞函數,調用它的函數將一直等待到被等待的線程結束為止。當函數返回時,被等待線程的資源就被回收。
pthread_create 函數:
pthread_exit函數
pthread_join函數
取消一個線程
有時候,我們想讓一個線程 能夠請求另外一個線程結束,就像給它發送一個訊號似的。用線程程是可以完成這一操作的,而與單處理經,線程在被要求結束執行的時候還有一種改變其行為的辦法。
我們來看看要求一個線程結束執行的函數
這個定義很明白,給定一個線程標識符,我們就能要求取消它。但在取消線形程請求的接收端,事情會稍微複雜一些,好在也不是太複雜。線形程可以用pthread_setcancelstate設定自己的取消狀態,下面是這個函數的定義:
如果取消請求被接受了,線程會進入第二個控制層次----用pthread_setcanceltype設定取消類型。
稍微注意一點就是在android-ndk-r3 裡是不支援int pthread_cancel(pthread_t thread); 所以想強制退出線程似乎沒有更好的辦法。
=================================================================================
linux多線程pthread的函式宣告在中,因此在使用該函數時,需要把該標頭檔引入。
線程的建立
1、建立
int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(* func) (void *), void *restrict arg );
attr: 線程屬性包括:優先順序、初始棧大小,是否應該成為一個守護線程。
預設設定,NULL
tidp是要建立的線程,建立成功後tipd為先線程的id
void *(* func) (void *)是一個函數指標,該函數指標的類型為void* (*)(void *)
是一個參數為void *,傳回值也為void *的函數類型。它的一個簡單的例子如下
void *thread_handler(void *arg)
{
return NULL;
}
void *restrict arg
中的arg是void *(* func) (void *)函數指標的參數。
補充:函式宣告中多次出現了restrict,其實這是用於CPU對函數的最佳化使用的,restrict的使用,由程式員保證使用restrict標誌的參數間不會有記憶體重疊。
擷取線程自身的id
pthread_t pthread_self(void);
等待給定線程終止
int pthread_join( pthread_t tid, void **status);
statues返回等待線程的傳回值
單個線程有三種退出方式
1.線程從啟動常式中返回(return方式),傳回值是現成的退出碼
2.線程被同一進程內的其他線程取消
3.線程調用pthread_exit退出。void pthread_exit(void *rval_ptr)
線程清理處理常式
void pthread_clean_push(void (*rtn)(void *),void *arg)
void pthread_clean_pop(iny excute)
清理函數rtn的調用順序是由pthread_clean_push函數安排的。
它在下列幾種情況下執行:
1.調用pthread_exit時
2.響應取消請求時
3.用非零execute參數調用pthread_clean_pop時
如果execute參數為0,清理函數將不被調用。無論何種情況,pthread_clean_pop都將刪除上次pthread_clean_push建立的清理處理常式。
如果線程使用return從常式返回,那麼pthread_clean_push建立的清理處理常式不會被執行。
linux thread與fork的對比