Solaris 多線程

?

1. ??????? 線程

創建一個缺省的線程

缺省的線程的屬性:

l???????? 非綁定

l???????? 未分離

l???????? 一個缺省大小的堆棧

l???????? 具有和父線程一樣的優先級

?

phread_attr_init() 創建一個缺省的屬性對象,

用屬性對象創建一個線程 pthread_create(3T)

?

int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void *(*start_routine)(void*), void *arg );

?

#include<pthread.h>

pthread_attr_t? tattr;

pthread_t? tid;

extern? void? *start_routine(void *arg);

void? *arg;

int? ret;

?

/*default behavior*/

ret = pthread_create( &tid, NULL, start_routine, arg );

?

/*init with default attributes*/

ret = pthread_attr_init( &tattr );

?

/*default behavior specified*/

ret = pthread_create( &tid, &tattr, start_routine, arg );

?

tattr 中含有初始化線程所需的屬性,值賦為 NULL 即缺省。 start_routine 是線程入口函數的起始地址。當 start_routine 返回時,相應的線程就結束了。線程結束時的退出狀態值是 start_routine 函數用 phread_exit() 函數返回的返回值。當 pthread_create() 函數調用成功時,線程標識符保存在參數 tid 指針指向中。

返回值, pthread_create() 成功后返回 0

EAGAIN 超過了某個限制,如 LWPs 過多。

EINVAL?? tattr 值非法。

?

創建子線程時,傳給子線程的輸入參數最好是 malloc() 返回的指針(這樣的指針指向進程堆中的存儲空間)或指向全局變量的指針,而不要是指向局部變量的指針。因為當子線程訪問輸入參數時,創建子線程的函數可能已結束,局部變量也就不存在了。

等待線程結束

?????? pthread_join(3T)

?????? int pthread_join( pthread_t tid, void **status );

?????? #include<pthread.h>

??????

?????? pthread_t? tid;

?????? int? ret;

?????? int? status;

?

?????? /*waiting to join thread “tid” with status*/

?????? ret = pthread_join( tid, &status );

??????

?????? /*waiting to join thread “tid” without status*/

?????? ret = pthread_join( tid, NULL );

??????

?????? pthread_join() 會阻塞調用它的線程,直到參數 tid 指定的線程結束。 tid 指定的線程必須在當前進程中,且必須是非分離的。 status 接收指定線程終止時的返回狀態碼。

?????? 不能有多個線程等待同一個線程終止,否則返回錯誤碼 ESRCH

?????? pthread_join() 返回時,終止線程占用的堆棧等資源已被回收。

?????? 返回值:成功返回 0

?????? ESRCH? tid 指定的線程不是一個當前線程中合法且未分離的線程。

?????? EDEADLK? tid 指定的是當前線程。

?????? EINVAL? tid 非法。

?

分離一個線程

?????? pthread_detach(3T)

?????? 將非分離線程設置為分離線程。

??????

?????? int? pthread_detach( pthread_t tid );

?????? #include<pthread.h>

?????? pthread_t? tid;

?????? int? ret;

?????? ret = pthread_detach( tid );

??????

?????? 該函數通知線程庫,當線程終止以后, tid 所指線程的內存可以被立即收回。

?????? 返回值:成功返回 0

?????? EINVAL? tid 所指線程不是一個合法線程。

?????? ESRCH? tid 指定的線程不是一個當前線程中合法且未分離的線程。

?

為線程數據創建一個鍵

?????? 多線程的 c 語言程序具有三種數據:局部變量,全局變量,線程數據( TSD

?????? TSD 類似于全局變量,但是線程私有的。

?????? 每個 TSD 都有個鍵同他相關聯。

?????? pthread_key_create(3T)

??????

?????? int pthread_key_create( pthread_key_t *key, void (*destructor)(*void) );

?????? #include<pthread.h>

?????? pthread_key_t? key;

?????? int? ret;

?????? /*key create without destructor*/

?????? ret = pthread_key_create( &key, NULL );

??????

?????? /*key create with destructor*/

?????? ret = pthread_key_destructor( &key, destructor );

??????

?????? 該函數成功時,份配的建放在 key 中,必須保證 key 指向的內存區有效。 destructor 用來釋放不再需要的內存。

?????? 返回值:成功返回 0

?????? EAGAIN? key 名字空間耗盡

?????? ENOMEM? 沒有足夠的內存空間創建一個新的鍵。

?

刪除線程數據的鍵

?????? pthread_key_delete(3T)

?????? solaris 線程接口中沒有該函數

??????

?????? int pthread_key_delete( pthread_key_t key );

?????? #include<pthread.h>

?????? pthread_key_t? key;

?????? int? ret;

?????? ret = pthread_key_delete( key );

?

?????? 在調用該函數之前,必須釋放和本線程相關聯的資源, pthread_key_delete() 不會引發鍵的解析函數。

?????? 返回值:成功返回 0

?????? EINVAL? key 值非法

?

設置線程數據鍵

?????? pthread_setspecific(3T)

?????? 設置和某個線程數據鍵綁定在一起的線程數據(一般是指針)

??????

?????? int? pthread_setspecific( pthread_key_t key, const void *value );

?????? #include<pthread.h>

?????? pthread_key_t? key;

?????? void *value;

?????? int? ret;

?????? ret = pthread_setspecific( key, value );

?

?????? 返回值:成功返回 0

?????? ENOMEM? 沒有足夠的虛擬內存

?????? EINVAL? key 值非法

?????? pthread_setspecific() 不釋放原來綁定在鍵上的內存,給一個鍵綁定新的指針時,必須釋放原指針指向的內存,否則會發生內存泄漏。

?

獲取線程數據鍵

?????? pthread_getspecific(3T)

?????? 獲取綁定在線程數據鍵上的值,并在指定的位置存儲值

??????

?????? int? pthread_getspecific( pthread_key_t key, void**value )

?????? #include<pthread.h>

?????? pthread_key_t? key;

?????? void? *value;

?????? pthread_getspecific( key, &value );

?

?????? 返回值:不返回錯誤碼

?

取線程標識符

?????? pthread_self(3T)

?????? 取當前線程的標識符

??????

?????? pthread_t? pthread_self( void );

?????? #include<pthread.h>

?????? pthread_t? tid;

?????? tid = pthread_self();

?

?????? 返回值:當前線程標識符。

?

比較線程標識符

?????? pthread_equal(3T)

??????

?????? int? pthread_equal( pthread_t tid1, pthread_t tid2 );

?????? #include<pthread.h>

?????? pthread_t? tid1,tid2

?????? int? ret;

?????? ret = pthread_equal( tid1, tid2 );

?

?????? 返回值:如果 tid1 tid2 相同返回非零值,否則返回 0 。如果參數非法,返回值不可預知。

?

初始化線程

?????? pthread_once(3T)

?????? 用來調用初始化函數,只有第一次調用有效。

?????? int? pthread_once( pthread_once_t *once_control, void(*init_routine)(void) );

?????? #include<pthread.h>

?????? pthread_once_t? once_control = PTHREAD_ONCE_INIT;

?????? int? ret;

?????? ret = pthread_once( &once_control, init_routine );

?

?????? once_control 界定了相應的初始化函數是否被調用過。

?????? 返回值:成功返回 0

?????? EINVAL? 某個參數為 NULL

?

出讓當前線程對處理器的控制權

?????? sched_yeild(3R)

?????? 把當前線程的優先權讓給有相同或更高優先級的線程。

?????? int? sched_yeild( void );

?????? #include<pthread.h>

?????? int? ret;

?????? ret = sched_yeild();

?

?????? 返回值:成功返回 0

?????? ENOSYS? 當前版本不支持 sched_yield()

?

設置線程的優先級

?????? pthread_setschedparam(3T)

??????

?????? int? pthread_setschedparam( pthread_t tid, int policy, const struct sched_param *param );

?????? #include<pthread.h>

?????? pthread_t? tid;

?????? int? ret;

?????? struct? sched_param? param;

?????? int? priority;

??????

?????? /*sched_priority will be the priority of the thread*/

?????? sched_param,sched_priority = priority;

?????? /*only supported policy ,other will result in ENOTSUP*/

?????? policy = SCHED_OTHER;

?????? /*scheduling parameters of target thread*/

?????? ret = pthread_setschedparam( tid, policy, &param );

??????

?????? 返回值:成功返回 0

EINVAL? 屬性值非法

ENOTSUP? 屬性值在當前版本不支持

?

取線程的優先級

?????? pthread_getschedparam(3T)

??????

?????? int? pthread_getschedparam( pthread_t tid, int policy, struct schedparam *param );

?????? #include<pthread.h>

?????? pthread_t? tid;

?????? sched_param? param;

?????? int? prioprity;

?????? int? policy;

?????? int? ret;

?????? /*scheduling parameters of target thread*/

?????? ret = pthread_getschedparam( tid, &policy, &param );

?????? /*sched_priority contains the priority of the thread*/

?????? priority = param.sched_priority;

?

?????? 返回值:成功返回 0

?????? ESRCH? tid 不是一個現存的線程。

?

向線程發信號

?????? pthread_kill(3T)

??????

?????? int? pthread_kill( pthread_t tid, int sig );

?????? #include<pthread.h>

?????? #include<signal.h>

?????? int? sig;

?????? pthread_t? tid;

?????? int? ret;

?????? ret = pthread_kill( tid, sig );

?

?????? tid 指定的線程必須和函數當前線程在同一個進程中。

?????? sig 0 時,進行錯誤檢查,不發送信號,往往被用來檢查 tid 的合法性。

?????? 返回值:成功返回 0

?????? EINVAL? sig 不是合法信號量

?????? ESRCH? tid 不是當前進程中的線程

?

訪問當前線程的信號掩碼

?????? pthread_sigmask(3T)

??????

?????? int? pthread_sigmask( int how, const sigset_t *new, sigset_t *old );

#include<pthread.h>

?????? #include<signal.h>

?????? int? ret;

?????? sigset_t? old, new;

?????? ret = pthread_sigmask( SIG_SETMASK, &new, &old );

?????? ret = pthread_sigmask( SIG_BLOCK, &new, &old );

ret = pthread_sigmask( SIG_UNBLOCK, &new, &old );

?

?????? how 表示對當前信號掩碼進行什么操作。

????????????? SIG_SETMASK :在信號掩碼中加入 new 信號集, new 表示新增加的要屏蔽的信號。

????????????? SIG_BLOCK :在信號掩碼中刪去 new 信號集, new 表示新增加的不需再屏蔽的信號。

????????????? SIG_UNBLOCK :用 new 信號集替換信號掩碼, new 表示所有需要屏蔽的信號。

?????? new NULL 時,無論 how 是什么,當前線程的信號掩碼都不會改變。

?????? 舊的信號掩碼保存在 old 中。

?????? 返回值:成功返回 0

?????? EINVAL? how 的值未定義

?

安全的復制

?????? pthread_atfork(3T)

??????

?????? int? pthread_atfork( void(*prepare)(void), void(*parent)(void), void(*child)(void) );

?

終止線程

?????? pthread_exit(3T)

??????

?????? void? pthread_exit(void *status);

?????? #include<pthread.h>

?????? int? status;

?????? pthread_exit( &status );

??????

?????? 終止當前線程,所有綁定在線程鍵上的內存將釋放。如果當前線程是未分離的,該線程的標識符和推出代碼( status )被保留,直到其它線程用 pthread_join() 等待當前線程的終止。如果當前線程是分離的, status 被忽略,線程標識符立即收回。

?????? 返回值:若 status 不為 NULL ,線程的退出代碼被置為 status 指向的值。

?

?????? 一個線程可以用一下方式終止自身運行。

?????? 從線程的入口函數返回。

?????? 調用 pthread_exit()

?????? POSIX pthread_cancel()

?

?????? 退出可以用以下方式:

?????? 異步的

?????? 由線程庫定義的一系列退出點

?????? 有應用程序定義的一系列退出點

?

?????? 退出點

?????? 由程序通過 pthread_testcancel() 建立

?????? 調用了 pthread_cond_wait() pthread_cond_timedwait() 等待一個條件的線程

?????? 調用了 pthread_join() 等待另一個線程結束的線程。

?????? 被阻塞在 sigwait(2) 上的線程。

?????? 一些標準的庫函數。

??????

退出線程

?????? pthread_cancel(3T)

??????

?????? int? pthread_cancel( pthread_t thread );

#include<pthread.h>

pthread_t? thread;

int? ret;

ret = pthread_cancel ( thread ) ;

?

返回值:成功返回 0

ESRCH? 無指定的線程。

?

允許或禁止退出

?????? pthread_setcancelstate(3T)

?????? 缺省是允許退出的。

?????? int? pthread_setcancelstate( int state, int *oldstate );

?????? #include<pthread.h>

?????? int? oldstate;

?????? int? ret;

?????? /*enable*/

?????? ret = pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );

?????? /*disabled*/

ret = pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );

?

返回值:成功返回 0

EINVAL? state 值非法

?

設置退出類型

?????? pthread_setcanceltype(3T)

?????? 可以設置成延遲類型或異步類型。缺省是延遲類型。異步類型下,線程可以在執行中的任何時候被退出。

?????? int? pthread_setcanceltype( int type, int *oldtype );

?????? #include<pthread.h>

?????? int? oldtype;

?????? int? ret;

?????? /*deferred mode*/

?????? ret = pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldtype );

?????? /*async mode*/

ret = pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype );

?

返回值:成功返回 0

EINVAL? state 值非法

?

創建退出點

?????? pthread_testcancel(3T)

?????? void? pthread_testcancel( void );

?????? #include<pthread.h>

?????? pthread_testcancel();

?

?????? 只有當線程的退出狀態是允許退出,退出類型是延遲類型時,有效。

?????? 沒有返回值。

?

將一個善后處理函數推入退出堆棧

?????? pthread_cleanup_push(3T)

?????? pthread_cleanup_pop(3T)

??????

?????? void Pthread_cleanup_push( void(*routine)(void*), void *args );

?????? void pthread_cleanup_pop( int execute );

?????? #include<pthread.h>

?????? /*push the handler “routine” on cleanup stack*/

?????? pthread_cleanup_push( routine, arg );

?????? /*pop the “func” out of cleanup stack and execute “func”*/

?????? pthread_cleanup_pop( 1 );

?????? /*pop the “func” and don’t execute “func”*/

?????? pthread_cleanup_pop( 0 );

?

?

1. ??????? 線程屬性

只能在線程創建時制定屬性,不能在運行時改變它。

一旦屬性對象被配置好,它在進程范圍內都是有效的。

?

初始化屬性

pthread_attr_init(3T)

?????? 初始化一個線程屬性對象,屬性值是缺省值,占用內存由線程庫分配。

?????? int? pthread_attr_init( pthread_attr_t *tattr );

?????? #include<pthread.h>

?????? pthread_attr_t? tattr;

?????? int? ret;

?????? /*initialize an attribute to the default value*/

?????? ret = pthread_attr_init( &tattr );

??????

?????? 屬性對象的缺省值:

?????? scope (線程域) ?????? PTHREAD_SCOPE_PROCESS

?????? Detachstate (分離狀態) ? PTHREAD_CREATE_JOINABLE

?????? Stackaddr (堆棧地址) ? NULL

?????? Stacksize (堆棧大小) ? 1Mb

?????? priority (優先級) ? 父進程優先級

?????? Inheritsched (繼承調度優先級) ? PTHREAD_INHERIT_SCHED

?????? schedpolicy (調度策略) ? SCHED_OTHER

??????

?????? 返回值:成功返回 0

?????? ENOMEM? 沒有足夠的內存初始化線程屬性對象

??????

釋放屬性對象

pthread_attr_destroy(3T)

??????

?????? int? pthread_attr_destroy( pthread_attr_t *tattr? );

?????? #include<pthread.h>

?????? pthread_attr_t? tattr;

?????? int? ret;

?????? ret = pthread_attr_destroy( &tattr );

??????

?????? 返回值:成功返回 0

?????? EINVAL? tattr 值非法

?

設置分離狀態

pthread_attr.setdetachstate(3T)

?????? 創建線程時,如果指定這個線程為分離線程,一旦這個線程終止,他的線程標識符和其他相關的資源可以立即被使用。如果不需要等待某個線程終止,可以把它設定為分離。

int? pthread_attr_setdetachstate( pthread_attr_t *tattr, int detachstate );

#include<pthread.h>

?????? pthread_attr_t? tattr;

?????? int? ret;

?????? /*set the thread detach state*/

?????? ret = pthread_attr_setdetachstate( &tattr, PTHREAD_CREATE_DETACHED );

??????

?????? 返回值:成功返回 0

?????? EINVAL? tattr 的值或 detachstate 的值非法

?

取分離狀態

pthread_attr_getdetachstate(3T)

?????? int? pthread_attr_getdetachstate( const pthread_attr_t *tattr, int *detachstate );

?????? #include<pthread.h>

?????? pthread_attr_t? tattr;

?????? int? detachstate;

?????? int? ret;

?????? ret = pthread_attr_getdetachstate( &tattr,? &detachstate );

?

?????? 返回值:成功返回 0

?????? EINVAL? tattr 的值或 detachstate 的值非法

?

?