国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

linux多線程編程總結

2019-11-09 17:35:40
字體:
來源:轉載
供稿:網友

linux的多線程發展歷史

在早期的LINUX內核中,并不存在真正意義上的線程。當時Linux中常用的線程pthread實際上是通過進程來模擬的,也就是同過fork來創建“輕”進程,并且這種輕進程的線程也有個數的限制,最多只能有4096和此類線程同時運行。2.4內核消除了個數上的限制,并且允許在系統運行中動態的調整進程數的上限,當時采用的是Linux Thread 線程庫,它對應的線程模型是“一對一”,而線程的管理是在內核為的函數庫中實現,這種線程得到了廣泛的應用。但是它不與POSIX兼容。另外還有許多諸如信號處理,進程ID等方面的問題沒有完全解決。

在的2.6內核中,進程調度通過重新的編寫,刪除了以前版本中的效率不高的算法,內核框架頁也被重新編寫。

開始使用NPTL(Native POSIX Thread Library)線程庫,這個線程庫有以下幾個目標: - POSIX兼容 - 低啟動開銷 - 低鏈接開銷 - 與Linux Thread應用的二進制兼容,軟硬件的可擴展能力,與C++集成等。

這一切使得2.6的內核多線程機制更加完備。從內核2.6內核開始linux開啟進入多線程時代

線程的基本操作

創建

#include <pthread.h>int pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);

參數 - pthread_t *restrict tidp:創建的的線程ID號 - const pthread_attr_t *restrict attr:指定線程的Attributes,若使用默認值可以設置為NULL - void (*start_rtn)(void ):線程運行時的任務(函數)指針 - void *restrict arg:運行start_rtn指針指向的函數時,傳入的參數

pthread_create出錯的時候不會設置errno,而是直接通過返回值返回錯誤代碼

屬性獲取與設置

id獲取

pthread_t pthread_self(void);

pthread_self可以獲取線程id號,而通過getpid獲取的是當前進程的pid。

pthread_attr_init屬性

typedef struct{ int detachstate; 線程的分離狀態 int schedpolicy; 線程調度策略 structsched_param schedparam; 線程的調度參數 int inheritsched; 線程的繼承性 int scope; 線程的作用域 size_t guardsize; 線程棧末尾的警戒緩沖區大小 int stackaddr_set; void* stackaddr; 線程棧的位置 size_t stacksize; 線程棧的大小}pthread_attr_t;

pthread_attr_init屬性對象主要包括是否綁定、是否分離、堆棧大小、優先級。默認的屬性為非綁定、非分離、缺省的堆棧、與父進程同樣級別的優先級。 - 綁定:關于線程的綁定,牽涉到另外一個概念:輕進程(LWP:Light Weight PRocess)。輕進程可以理解為內核線程,它位于用戶層和系統層之間。系統對線程資源的分配、對線程的控制是通過輕進程來實現的,一個輕進程可以控制一個或多個線程。 默認狀況下,啟動多少輕進程、哪些輕進程來控制哪些線程是由系統來控制的,這種狀況即稱為非綁定的。綁定狀況下,則顧名思義,即某個線程固定的”綁”在一個輕進程之上。被綁定的線程具有較高的響應速度,這是因為CPU時間片的調度是面向輕進程的,綁定的線程可以保證在需要的時候它總有一個輕進程可用。通過設置被綁定的輕進程的優先級和調度級可以使得綁定的線程滿足諸如實時反應之類的要求。pthread_attr_setscope可以設定線程的綁定狀態

/*設置線程綁定狀態的函數為 pthread_attr_setscope,它有兩個參數,第一個是指向屬性結構的指針,第二個是綁定類型,它有兩個取值: PTHREAD_SCOPE_SYSTEM(綁定的):表示與系統中所有線程一起競爭CPU時間 ,PTHREAD_SCOPE_PROCESS(非綁定的):表示僅與同進程中的線程競爭CPU*/pthread_attr_t attr;pthread_t tid;/*初始化屬性值,均設為默認值*/pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);pthread_create(&tid, &attr, (void *) my_function, NULL);//獲取當前的模式int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope);分離模式設置:線程分為分離模式和非分離模式,顧名思義在分離模式下,當線程退出時,所有的資源都會自動釋放。非分離的線程A終止時,其線程ID和退出狀態將保留,直到另外一個線程調用 pthread_join(A)。設置線程分離狀態的函數為 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)第二個參數可選為PTHREAD_CREATE_DETACHED(分離線程)和 PTHREAD _CREATE_JOINABLE(非分離線程)pthread_attr_t attr;pthread_t tid;/*初始化屬性值,均設為默認值*/pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);pthread_create(&tid, &attr, (void *) my_function, NULL);//也可以直接調用pthread_detach完成分離模式的設置int pthread_detach(pthread_t tid);//獲取當前的模式int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)/*值得注意的是:如果設置一個線程為分離線程,而這個線程運行又非???,它很可能在pthread_create函數返回之前就終止了,它終止以后就可能將線程號和系統資源移交給其他的線程使用,這樣調用pthread_create的線程就得到了錯誤的線程號。要避免這種情況可以采取一定的同步措施,最簡單的方法之一是可以在被創建的線程里調用pthread_cond_timewait函數,讓這個線程等待一會兒,留出足夠的時間讓函數pthread_create返回。設置一段等待時間,是在多線程編程里常用的方法。*/堆棧設置:默認棧的大小為8M,若直接在棧上分配一個較大的緩存char p[1024*1024*8];毫無疑問一定會提示段錯誤??梢酝ㄟ^pthread_attr_setstacksize設置棧的大小。pthread_attr_t attr; int size;//獲取當前棧的大小pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); //設置棧的大小pthread_attr_setstacksize(&attr, size)調度策略:通過pthread_attr_getschedpolicy和pthread_attr_setschedpolicy獲取和設置調度策略。調度策略可能的值是先進先出(SCHED_FIFO)、輪轉法(SCHED_RR),或其它(SCHED_OTHER)。int pthread_attr_getschedpolicy(const pthread_attr_t*attr,int *policy);int pthread_attr_setschedpolicy(pthread_attr_t *attr,intpolicy);優先級:通過pthread_attr_getschedparam 和pthread_attr_setschedparam分別用來設置和得到線程的調度參數(優先級)//函數原型int pthread_attr_getschedparam(const pthread_attr_t*attr,struct sched_param *param);int pthread_attr_setschedparam(pthread_attr_t *attr,conststruct sched_param *param);struct sched_param{ intsched_priority;};#include <pthread.h>#include <sched.h>pthread_attr_t attr; pthread_t tid;sched_param param;int newprio=20; /*初始化屬性*/pthread_attr_init(&attr); /*設置優先級*/pthread_attr_getschedparam(&attr, &param); param.sched_priority=newprio;pthread_attr_setschedparam(&attr, &param);pthread_create(&tid, &attr, (void *)myfunction, myarg);銷毀pthread_attr_t int pthread_attr_destroy(pthread_attr_t*attr);要記得用完后一定要destroy.POSIX 標準要求: When a thread attributes object is no longer required, it should be destroyed using the pthread_attr_destroy() function. Destroying a thread attributes object has no effect on threads that were created using that object.

退出

可以通過return直接退出可以通過調用pthread_exit退出可以通過其他的線程調用void pthread_cancel(pthread_t tid)通知退出

若線程A調用pthread_join(B, &rval_ptr)后被阻塞,直到B退出。若A需要直到B 的退出代碼,則需要調用phtread_exit(rval_ptr)退出,但rval_ptr指向的內存的生命周期,不應該指向B的Stack中的數據。

pthread_cleanup_push 與pthread_cleanup_pop通常配合pthread_cancel使用,完成后續的清理工作!

#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <pthread.h> #include <unistd.h>static void pthread_func_1 (void *); static void pthread_func_2 (void *); static void * pthread_func_3(void * );static void clean_fun1(void * );static void clean_fun2(void * );/*線程1:pthread_func_1 游離模式,主動調用pthread_exit退出線程2:pthread_func_2 非游離模式,通過return退出。線程3:pthread_func_3 非游離模式,主線程調用pthread_cancel 使其退出,配合pthread_cleanup_push 與pthread_cleanup_pop 做后續的清理工作!*/int main (int argc, char** argv) { pthread_t pt_1 = 0; pthread_t pt_2 = 0; pthread_t pt_3 = 0; pthread_attr_t atrr = {0}; int ret = 0; printf("threat test!/n"); /*初始化屬性線程屬性*/ pthread_attr_init (&atrr); pthread_attr_setscope (&atrr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate (&atrr, PTHREAD_CREATE_DETACHED); ret = pthread_create (&pt_1, &atrr, pthread_func_1, NULL); if (ret != 0) { perror ("pthread_1_create"); } ret = pthread_create (&pt_2, NULL, pthread_func_2, NULL); if (ret != 0) { perror ("pthread_2_create"); } ret = pthread_create (&pt_3, NULL, pthread_func_3, NULL); if (ret != 0) { perror ("pthread_3_create"); } printf("waiting for pthread_2 exiting!/n"); pthread_join (pt_2, NULL); printf("pthread_2 has exited!/n"); printf("begin to cancel pthread_3!/n"); sleep(2); ret=pthread_cancel(pt_3); if(ret!=0) { perror("cancel error:"); exit(0); } printf("waiting for pthread_3 exiting!/n"); pthread_join (pt_3, NULL); printf("pthread_3 has exited!/n"); return 0; } static void pthread_func_1 (void * para) { int i = 0; for (; i < 6; i++) { printf ("This is pthread_1./n"); if (i == 2) { pthread_exit (0); } } return; } static void pthread_func_2 (void * para) { int i = 0; for (; i < 4; i ++) { sleep(1); printf ("This is pthread_2./n"); } printf ("pthread_2 will be exit!/n"); return; } static void * pthread_func_3(void * arg){ int i=0; pthread_cleanup_push(clean_fun1,NULL); pthread_cleanup_push(clean_fun2,NULL); for(i=0 ; i<100 ; i++) { sleep(1); printf ("This is pthread_3./n"); } //這里要注意,如果將sleep(100);換成while(1);的話,程序會一直暫停.push和pop要成對出現. //因為while(1);運行的太快,線程不接受cancel信號 //while(1); pthread_cleanup_pop(0); pthread_cleanup_pop(0); return NULL;}static void clean_fun1(void * arg){ printf("this is clean fun1/n");}static void clean_fun2(void * arg){ printf("this is clean fun2/n");}

gcc -g -pthread threadTest.c -lpthread -o test 生成測試代碼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 繁昌县| 顺平县| 宜春市| 鄱阳县| 中方县| 金溪县| 荔浦县| 阿克陶县| 连平县| 会宁县| 姜堰市| 依安县| 肇东市| 万荣县| 平塘县| 贵溪市| 腾冲县| 淳安县| 盐源县| 区。| 新巴尔虎左旗| 赣州市| 呼伦贝尔市| 巴南区| 渭南市| 中西区| 灵石县| 乌拉特前旗| 康平县| 彭阳县| 隆子县| 吉木萨尔县| 哈密市| 修武县| 砀山县| 砀山县| 呼和浩特市| 醴陵市| 平武县| 高密市| 平和县|