在之前的章節中,我們在呼叫pthread_create函式創建執行緒時,第二個引數(即執行緒屬性)都是設為NULL,即使用默認屬性,一般情況下,使用默認屬性已經可以解決我們開發程序中的大多數問題,
但是,有時專案中我們對執行緒會有些特殊的要求,比如修改執行緒堆疊的大小,直接呼叫執行緒的庫函式無法滿足需求,在這種情況下我們可以直接對執行緒屬性進行設定,
型別pthread_attr_t是一個結構體,主要包括如下屬性:作用域(scope)、堆疊尺寸(stack size)、堆疊地址(stack address)、優先級(priority)、分離的狀態(detached state)、調度策略和引數(scheduling policy and parameters),
執行緒默認的屬性為非系結、非分離、預設的堆疊、與父行程同樣級別的優先級,結構體具體定義如下:
typedef struct
{
? int etachstate; //執行緒的分離狀態
? int schedpolicy; //執行緒調度策略
? struct sched_param schedparam; //執行緒的調度引數
? int inheritsched; //執行緒的繼承性
? int cope; //執行緒的作用域
? size_t guardsize; //執行緒堆疊末尾的警戒緩沖區大小
? int stackaddr_set; //執行緒的堆疊設定
? size_t stacksize; //執行緒堆疊的大小
} pthread_attr_t;
主要結構體成員:
? 1. 執行緒分離狀態:etachstate
? 2. 執行緒堆疊大小(默認平均分配):stacksize
? 3. 執行緒堆疊警戒緩沖區大小(位于堆疊末尾):guardsize
執行緒的屬性值不能直接設定,須使用相關函式進行操作,屬性的初始化的函式為pthread_attr_init,這個函式必須在pthread_create函式之前呼叫,使用完畢之后需呼叫pthread_attr_destroy函式來釋放資源,
執行緒屬性初始化
函式原型:
int pthread_attr_init(pthread_attr_t *attr);
回傳值:
成功:0;失敗:錯誤號,
函式作用:
初始化執行緒屬性;
注意:應先初始化執行緒屬性,再呼叫pthread_create創建執行緒,
執行緒屬性銷毀
函式原型:
int pthread_attr_destroy(pthread_attr_t *attr);
回傳值:
成功:0;失敗:錯誤號
函式作用:
銷毀執行緒屬性所占用的資源
執行緒的分離狀態
執行緒的分離狀態決定一個執行緒最后終止的時候是以怎樣的方式回收資源,
非分離狀態:執行緒的默認屬性是非分離狀態,這種情況下,執行緒運行結束后,只有當其它執行緒呼叫pthread_join()函式去回收它時,創建的執行緒才算終止,才能釋放自己占用的系統資源,
分離狀態:執行緒如果設定為分離狀態,則它將主動與主控執行緒脫離關系,當它自己運行結束了,執行緒也就終止了,馬上釋放系統資源,
設定執行緒分離狀態的函式:
設定執行緒屬性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
獲取程屬性
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
引數:attr:指向一個執行緒屬性的指標
detachstate:執行緒分離狀態
PTHREAD_CREATE_DETACHED(分離執行緒)
PTHREAD _CREATE_JOINABLE(非分離執行緒)
執行緒的堆疊地址
POSIX.1定義了兩個常量_POSIX_THREAD_ATTR_STACKADDR 和_POSIX_THREAD_ATTR_STACKSIZE檢測系統是否支持堆疊屬性,也可以給sysconf函式傳遞_SC_THREAD_ATTR_STACKADDR或 _SC_THREAD_ATTR_STACKSIZE來進行檢測,
當行程堆疊地址空間不夠用時,指定新建執行緒使用由malloc分配的空間作為自己的堆疊空間,通過pthread_attr_setstack和pthread_attr_getstack兩個函式分別設定和獲取執行緒的堆疊地址,
設定執行緒的堆疊地址:
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
成功:0;失敗:錯誤號
獲取執行緒的堆疊地址:
int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
成功:0;失敗:錯誤號
引數:attr:指向一個執行緒屬性的指標
stackaddr:回傳獲取的堆疊地址
stacksize:回傳獲取的堆疊大小
執行緒的堆疊大小
當系統中有很多執行緒時,可能需要減小每個執行緒堆疊的默認大小,防止行程的地址空間不夠用,當執行緒呼叫的函式會分配很大的區域變數或者函式呼叫層次很深時,可能需要增大執行緒堆疊的默認大小,
函式pthread_attr_getstacksize和 pthread_attr_setstacksize可以設定或者獲取執行緒的堆疊大小,
設定執行緒堆疊大小:
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
成功:0;失敗:錯誤號
獲取執行緒堆疊大小:
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
成功:0;失敗:錯誤號
引數:attr:指向一個執行緒屬性的指標
stacksize:回傳執行緒的堆疊大小
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define SIZE 0x10000
void *th_fun(void *arg)
{
while (1)
sleep(1);
}
int main(void)
{
pthread_t tid;
int err, detachstate, i = 1;
pthread_attr_t attr;
size_t stacksize; //typedef size_t unsigned int
void *stackaddr;
pthread_attr_init(&attr);
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_getdetachstate(&attr, &detachstate);
if (detachstate == PTHREAD_CREATE_DETACHED) //默認是分離態
printf("thread detached\n");
else if (detachstate == PTHREAD_CREATE_JOINABLE) //默認時非分離
printf("thread join\n");
else
printf("thread un known\n");
/* 設定執行緒分離屬性 */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
while (1) {
/* 在堆上申請記憶體,指定執行緒堆疊的起始地址和大小 */
stackaddr = malloc(SIZE);
if (stackaddr == NULL) {
perror("malloc");
exit(1);
}
stacksize = SIZE;
pthread_attr_setstack(&attr, stackaddr, stacksize); //借助執行緒的屬性,修改執行緒堆疊空間大小
err = pthread_create(&tid, &attr, th_fun, NULL);
if (err != 0) {
printf("%s\n", strerror(err));
exit(1);
}
printf("%d\n", i++);
}
pthread_attr_destroy(&attr);
return 0;
}
更多精彩內容,請關注公眾號良許Linux,公眾內回復1024可免費獲得5T技術資料,包括:Linux,C/C++,Python,樹莓派,嵌入式,Java,人工智能,等等,公眾號內回復進群,邀請您進高手如云技術交流群,
公眾號:良許Linux
有識訓?希望老鐵們來個三連擊,給更多的人看到這篇文章
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/152068.html
標籤:Linux
上一篇:Linux系統編程 —執行緒屬性
