線程原語
線程(thread),有時被稱為輕量級進程(Lightweight Process,LWP)。是程序運行流的最小單元。一個標准的線程由線程ID。當前指令指針(PC),寄存器集合和堆棧組成。
很多其他詳解看百度百科:線程。
在Linux shell下通過命令 $ ps -Lf pid 查看指定pid號下的全部線程。
這裡的線程是指同一進程下的線程。
共享:
1.文件描寫敘述符表
2.每種信號的處理方式
3.當前工作文件夾
4.用戶ID和組ID
5.內存地址空間
非共享:
1.線程id
2.處理器現場和棧指針(內核棧)
3.獨立的棧空間(用戶空間棧)
4.errno變量
5.信號屏蔽字
6.調度優先級
通過命令 $ man -k pthread 查看系統下與線程有關的全部函數。
一般的,把main函數稱作主線程或主控線程,其他線程都稱作是子線程。
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
pthread_t *thread:傳遞一個pthread_t變量地址進來,用於保存新線程的tid(線程ID)
const pthread_attr_t *attr:線程屬性設置。如使用默認屬性,則傳NULL
void *(*start_routine)(void *):函數指針。指向新線程應該載入運行的函數模塊
void *arg:指定線程將要載入調用的那個函數的參數
返回值:成功返回0,失敗返回錯誤號。
曾經學過的系統函數都是成功返回0,失敗返回-1。而錯誤號保存在全局變量errno中,而pthread庫的函數都是通過返回值返回錯誤號,盡管每一個線程也都有一個errno,但這是為了兼容其他函數接口而提供的,pthread庫本身並不使用它。通過返回值返回錯誤碼更加清晰。
Compile and link with -lpthread.
typedef unsigned long int pthread_t; //在不同的系統中pthread_t可能會有不同的實現
假設須要僅僅終止某個線程而不終止整個進程。能夠有三種方法:
1.return。
這樣的方法對主控線程不適用。從main函數return相當於調用exit。
2.一個線程能夠調用pthread_cancel終止同一進程中的還有一個線程。
#include <pthread.h> int pthread_cancel(pthread_t thread);被取消的線程,退出值。定義在Linux的pthread庫中常數PTHREAD_CANCELED的值是-1。能夠在頭文件pthread.h中找到它的定義:#define PTHREAD_CANCELED ((void *) -1)。也就是說,被pthread_cancel結束的線程,退出值,都是-1。
同一進程的線程間,pthread_cancel向還有一線程發終止信號。
系統並不會立即關閉被取消線程,僅僅有在被取消線程下次系統調用時,才會真正結束線程。
或調用pthread_testcancel,讓內核去檢測是否須要取消當前線程。
3.線程能夠調用pthread_exit終止自己。
#include <pthread.h> void pthread_exit(void *retval); void *retval:線程退出時傳遞出的參數。能夠是退出值或地址,如是地址時,不能是線程內部申請的局部地址。
在不論什麼地方調用exit,都會使整個進程退出。
#include <pthread.h> pthread_t pthread_self(void); RETURN VALUE This function always succeeds, returning the calling thread’s ID.在線程中使用pthread_self。獲取線程id。
#include <pthread.h> int pthread_join(pthread_t thread, void **retval); pthread_t thread:回收線程的tid void **retval:接收退出線程傳遞出的返回值 返回值:成功返回0。失敗返回錯誤號同進程相似,線程退出後,相同須要進行回收,所以pthread_join相似於wait。調用該函數的線程將掛起等待,直到id為thread的線程終止。thread線程以不同的方法終止,通過pthread_join得到的終止狀態是不同的。總結例如以下:
//thread_exit.c #include <stdio.h> #include <unistd.h> #include <pthread.h> void *fun_1(void *argv) { printf("Hello %s,my thread id is %x\n", (char*)argv, pthread_self()); sleep(1); //pthread_exit((void*)1); return (void*)1; } void *fun_2(void *argv) { printf("Hello %c, my thread id is %x\n", (char)argv, pthread_self()); sleep(2); pthread_exit((void*)"David"); } int main(void) { int *ret1; char *ret2; pthread_t tid1, tid2; pthread_create(&tid1, NULL, fun_1, (void*)"zhangxiang"); pthread_create(&tid2, NULL, fun_2, (void*)'D'); pthread_join(tid1, (void*)&ret1); pthread_join(tid2, (void*)&ret2); printf("thread %x exit with %x\n", tid1, ret1); printf("thread %x exit with %s\n", tid2, ret2); return 0; } $ gcc thread_exit.c -lpthread $ ./a.out Hello D, my thread id is 745e9700 Hello zhangxiang, my thread id is 74fea700 thread 74fea700 exit with 1 thread 745e9700 exit with David
//thread_cancel.c #include <stdio.h> #include <pthread.h> void *fun(void *argv) { printf("thread %x running\n", pthread_self()); pthread_exit((void*)0); } int main(void) { pthread_t tid; void *ret; pthread_create(&tid, NULL, fun, NULL); pthread_join(tid, &ret); printf("thread %x exit with %d\n", tid, (int)ret); pthread_create(&tid, NULL, fun, NULL); pthread_cancel(tid); pthread_join(tid, &ret); printf("thread %x exit with %d\n", tid, (int)ret); return 0; } $ gcc thread_cancel.c -lpthread $ a.out thread 96da9700 running thread 96da9700 exit with 0 thread 96da9700 running thread 96da9700 exit with -1
CCPP Blog 文件夾