Thread簡介
在同一個程式中的每個thread會共用全域記憶體, 包括
- 初始化資料(initialized data)
- 未初始化資料(uninitialized data)
- heap segment
使用fork()的問題:
- process之間資訊較難以共用
- 使用fork()建立process成本較高, 需要複製如page table和file descriptor table之類的各種process屬性
改用thread可以改善這些問題
- thread之間可以簡便快速的分享資訊, 只需要將資料複製共用變數中.
- fork()建立sub process需要複製許多屬性, 而thread本來就共用這些屬性
Thread共用屬性和各自有的屬性:
共用屬性:
- process ID 和 parent process ID
- process群組id和作業階段id(session ID)
- 控制終端機(controlling terminal)
- 行程憑證(process credential)(使用者ID與群組ID)
- 開啟的file descriptors
- 使用fcntl()建立的recording lock(紀錄鎖)
- signal處理
- 檔案系統的相關資訊: 權限遮罩(umask), 目前工作目錄和根目錄
- 間隔計時器(setitimer())與POSIX計時器(timer_create())
- System V(system v)號誌undo(semadj)
- 資源限制(resource limit)
- CPU時間消耗(由times()傳回)
- 資源消耗(由getrusage()傳回)
- nice值(由setpriority()與nice()設定)
各自擁有的屬性:
- thread ID
- 訊號遮罩(signal mask)
- 執行緒特有的資料
- 替代的訊號堆疊(sigaltstack())
- errno變數
- 浮點(floating-point)環境
- 即時排班策略(real-time scheduling policy)和優先權
- CPU affinity
- 能力(capability)
- 堆疊(stack), 區域變數和函式的呼叫連結
Pthread API簡介:
資料型別
|
說明
|
pthread_t
|
|
pthread_mutex_t
|
互斥(Mutex)
|
pthread_mutexattr_t
|
互斥屬性物件
|
pthread_cond_t
|
條件變數(condition variable)
|
pthread_condattr_t
|
條件變數的屬性物件
|
pthread_key_t
|
Thread特有的資料鍵(Key)
|
pthread_once_t
|
一次性的初始化控制上下文(One-time initialization control context)
|
pthread_attr_t
|
Thread的屬性物件
|
中止Thread的方式
- thread的start函式return並傳回指定回傳值
- thread呼叫pthread_exit()
- 使用pthread_cancel()取消thread
- 任何呼叫exit()的thread或主thread進行return都會導致process中的所有threads全部終止
Pthread函式操作
pthread_create()
int pthread_create(pthread_t *thread, const pthread_atr_t *attr, void *(*start)(volid * ), void *arg)
- 產生一個新的thread
- pthread_create()的thread會去執行start()函式, arg則是要傳給start函式的參數
- 通常arg是指向一個全域變數或堆積(heap)變數, 也可以設為NULL
- 傳遞多個arg給start()可以將arg指向一個struct的指標, 將參數放在該struct各欄位
- thread是一個buffer用來存threadID
- attr用來指定新thread的各種屬性, NULL為預設值
pthread_exit()
void pthread_exit(void *retval)
- 終止呼叫pthread_exit()的thread
- 呼叫pthread_exit()等同於在thread的start()中呼叫return
- retval指定thread的回傳值, 並建議retval所指定值不應該配置在stack中
- 主thread呼叫了pthread_exit()而非exit()或return, 則其他thread會繼續執行
pthread_self()
pthread_t pthread_self(void)
- 取得自己的threadID
pthread_equal()
int pthread_equal(pthread_t t1, pthread_t t2)
- 檢查兩個threadID是否相同
- 回傳非0表示相同, 回傳0表示不同
pthread_join()
int pthread_join(pthread_t thread, void **retval)
- 此函式會等待為threadID的thread終止, 此操作稱為joining(併入)
- 若retval不為NULL會儲存終止的thread回傳值得副本. 此回傳值就是thread return或呼叫pthread_exit()所指定的值
- 不可重複joining同一個thread, 會發生無法預期的情形
- thread尚未分離(detached)若我們joining thread失敗的話會產生zombie thread. zombie thread多到一定數量就無法在產生新的thread
pthread_detach()
int pthread_detach(pthread_t thread)
- 不需要thread的回傳狀態, 只需要系統能在thread終止時去回收並清理thread.可以使用pthread_detach()將thread標示成detached狀態
- thread可以對自己標示成detached狀態
- pthread_deatch(pthread_self())
- 標示成detached的thread無法被其他thread使用pthread_join()來取得thread狀態
- 若其他thread呼叫exit(), detached thread仍會被終止
Thread屬性的使用範例
pthread_t thr;
pthread_attr_t attr;
int s;
s = pthread_attr_init(&attr); /* Assigns default values */
if (s != 0)
errExitEN(s, "pthread_attr_init");
s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (s != 0)
errExitEN(s, "pthread_attr_setdetachstate");
s = pthread_create(&thr, &attr, threadFunc, (void *) 1);
if (s != 0)
errExitEN(s, "pthread_create");
s = pthread_attr_destroy(&attr); /* No longer needed */
if (s != 0)
errExitEN(s, "pthread_attr_destroy");
s = pthread_join(thr, NULL);
if (s != 0)
errExitEN(s, "pthread_join failed as expected");
沒有留言:
張貼留言