天天看點

線程屬性(多線程程式設計筆記)線程屬性

線程屬性

前篇介紹了使用預設屬性建立線程的基本原理。本章論述如何在建立線程時設定

屬性。

注– 隻有pthreads 使用屬性和取消功能。本章中介紹的API 僅适用于POSIX 線程。除此

之外,Solaris 線程和pthreads 的功能大緻是相同的。

屬性對象

通過設定屬性,可以指定一種不同于預設行為的行為。使用

pthread_create(3C)

建立

線程時,或初始化同步變量時,可以指定屬性對象。預設值通常就足夠了。

屬性對象是不透明的,而且不能通過指派直接進行修改。系統提供了一組函數,用于

初始化、配置和銷毀每種對象類型。

初始化和配置屬性後,屬性便具有程序範圍的作用域。使用屬性時最好的方法即是在

程式執行早期一次配置好所有必需的狀态規範。然後,根據需要引用相應的屬性對

象。

使用屬性對象具有兩個主要優點。

■ 使用屬性對象可增加代碼可移植性。

即使支援的屬性可能會在實作之間有所變化,但您不需要修改用于建立線程實體的

函數調用。這些函數調用不需要進行修改,因為屬性對象是隐藏在接口之後的。

如果目标系統支援的屬性在目前系統中不存在,則必須顯式提供才能管理新的屬

性。管理這些屬性是一項非常容易的移植任務,因為隻需在明确定義的位置初始化

屬性對象一次即可。

■ 應用程式中的狀态規範已被簡化。

例如,假設程序中可能存在多組線程。每組線程都提供單獨的服務。每組線程都有

各自的狀态要求。

在應用程式執行初期的某一時間,可以針對每組線程初始化線程屬性對象。以後所

有線程的建立都會引用已經為這類線程初始化的屬性對象。初始化階段是簡單和局

部的。将來就可以快速且可靠地進行任何修改。

在程序退出時需要注意屬性對象。初始化對象時,将為該對象配置設定記憶體。必須将此内

存傳回給系統。pthreads 标準提供了用于銷毀屬性對象的函數調用。

初始化屬性

請使用

pthread_attr_init(3C)

将對象屬性初始化為其預設值。存儲空間是在執行期間

由線程系統配置設定的。

pthread_attr_init

文法

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); 
           

表1 給出了屬性(tattr) 的預設值。

屬性 結果
scope

PTHREAD_SCOPE_PROCESS

新線程與程序中的其他線程發生競争。
detachstate

PTHREAD_CREATE_JOINABLE

線程退出後,保留完成狀态和線程ID。
stackaddr NULL 新線程具有系統配置設定的棧位址。
stacksize 新線程具有系統定義的棧大小。
priority 新線程的優先級為0。
inheritsched

PTHREAD_EXPLICIT_SCHED

新線程不繼承父線程排程優先級。
schedpolicy

SCHED_OTHER

新線程對同步對象争用使用Solaris 定義的固定優先級。線程将一直運作,直到被搶占或者直到線程阻塞或停止為止。

pthread_attr_init

傳回值

pthread_attr_init()

成功完成後将傳回零。其他任何傳回值都表示出現了錯誤。如果

出現以下情況,該函數将失敗并傳回對應的值。

ENOMEM

描述: 如果未配置設定足夠的記憶體來初始化線程屬性對象,将傳回該值。

銷毀屬性

請使用

pthread_attr_destroy(3C)

删除初始化期間配置設定的存儲空間。屬性對象将會無

效。

pthread_attr_destroy

文法

int pthread_attr_destroy(pthread_attr_t *tattr);
           
#include <pthread.h>
pthread_attr_t tattr;
int ret;
/* destroy an attribute */
ret = pthread_attr_destroy(&tattr);
           

pthread_attr_destroy

傳回值

pthread_attr_destroy()

成功完成後将傳回零。其他任何傳回值都表示出現了錯誤。如

果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 訓示tattr 的值無效。

設定分離狀态

如果建立分離線程(

PTHREAD_CREATE_DETACHED

),則該線程一退出,便可重用其線程ID

和其他資源。如果調用線程不準備等待線程退出,請使用

pthread_attr_setdetachstate(3C)

pthread_attr_setdetachstate(3C)

文法

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); 
           

如果使用

PTHREAD_CREATE_JOINABLE

建立非分離線程,則假設應用程式将等待線程完

成。也就是說,程式将對線程執行

pthread_join()

無論是建立分離線程還是非分離線程,在所有線程都退出之前,程序不會退出。

注– 如果未執行顯式同步來防止新建立的分離線程失敗,則線上程建立者從

pthread_create()

傳回之前,可以将其線程ID 重新配置設定給另一個新線程。

非分離線程在終止後,必須要有一個線程用join 來等待它。否則,不會釋放該線程的

資源以供新線程使用,而這通常會導緻記憶體洩漏。是以,如果不希望線程被等待,請

将該線程作為分離線程來建立。

示例1建立分離線程

#include <pthread.h>
pthread_attr_t tattr;
pthread_t tid;
void *start_routine;
void arg
int ret; 

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
ret = pthread_attr_setdetachstate (&tattr,PTHREAD_CREATE_DETACHED);
ret = pthread_create (&tid, &tattr, start_routine, arg); 
           

pthread_attr_setdetachstate

傳回值

pthread_attr_setdetachstate()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 訓示detachstate 或tattr 的值無效。

擷取分離狀态

請使用

pthread_attr_getdetachstate(3C)

檢索線程建立狀态(可以為分離或連接配接)。

pthread_attr_getdetachstate

文法

int pthread_attr_getdetachstate(const pthread_attr_t *tattr,
        int *detachstate)
           
#include <pthread.h>
pthread_attr_t tattr;
int detachstate;
int ret;

/* get detachstate of thread */
ret = pthread_attr_getdetachstate (&tattr, &detachstate); 
           

pthread_attr_getdetachstate

傳回值

pthread_attr_getdetachstate()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 訓示detachstate 的值為NULL 或tattr 無效。

設定棧溢出保護區大小

pthread_attr_setguardsize(3C)

可以設定attr 對象的guardsize。

pthread_attr_setguardsize(3C)

文法

#include <pthread.h>
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); 
           

出于以下兩個原因,為應用程式提供了guardsize 屬性:

■ 溢出保護可能會導緻系統資源浪費。如果應用程式建立大量線程,并且已知這些線

程永遠不會溢出其棧,則可以關閉溢出保護區。通過關閉溢出保護區,可以節省系

統資源。

■ 線程在棧上配置設定大型資料結構時,可能需要較大的溢出保護區來檢測棧溢出。

guardsize 參數提供了對棧指針溢出的保護。如果建立線程的棧時使用了保護功能,則

實作會在棧的溢出端配置設定額外記憶體。此額外記憶體的作用與緩沖區一樣,可以防止棧指

針的棧溢出。如果應用程式溢出到此緩沖區中,這個錯誤可能會導緻SIGSEGV 信号被發

送給該線程。

如果guardsize 為零,則不會為使用attr 建立的線程提供溢出保護區。如果guardsize 大

于零,則會為每個使用attr 建立的線程提供大小至少為guardsize 位元組的溢出保護區。

預設情況下,線程具有實作定義的非零溢出保護區。

允許合乎慣例的實作,将guardsize 的值向上舍入為可配置的系統變量PAGESIZE 的倍

數。請參見sys/mman.h 中的

PAGESIZE

。如果實作将guardsize 的值向上舍入為

PAGESIZE

的倍數,則以guardsize(先前調用

pthread_attr_setguardsize()

時指定的溢出保護區

大小)為機關存儲對指定attr 的

pthread_attr_getguardsize()

的調用。

pthread_attr_setguardsize

傳回值

如果出現以下情況,

pthread_attr_setguardsize()

将失敗:

EINVAL

描述: 參數attr 無效,參數guardsize 無效,或參數guardsize 包含無效值。

擷取棧溢出保護區大小

pthread_attr_getguardsize(3C)

可以擷取attr 對象的guardsize。

pthread_attr_getguardsize

文法

#include <pthread.h>
int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize); 
           

允許一緻的實作将guardsize 中包含的值向上舍入為可配置系統變量PAGESIZE 的倍數。

請參見sys/mman.h 中的

PAGESIZE

。如果實作将guardsize 的值向上舍入為

PAGESIZE

的倍

數,則以guardsize(先前調用

pthread_attr_setguardsize()

時指定的溢出保護區大

小)為機關存儲對指定attr 的

pthread_attr_getguardsize()

的調用。

pthread_attr_getguardsize

傳回值

如果出現以下情況,

pthread_attr_getguardsize()

将失敗:

EINVAL

描述: 參數attr 無效,參數guardsize 無效,或參數guardsize 包含無效值。

設定範圍

請使用

pthread_attr_setscope(3C)

建立線程的争用範圍(

PTHREAD_SCOPE_SYSTEM

PTHREAD_SCOPE_PROCESS

)。使用

PTHREAD_SCOPE_SYSTEM

時,此線程将與系統中的所有

線程進行競争。使用

PTHREAD_SCOPE_PROCESS

時,此線程将與程序中的其他線程進行競

争。

注– 隻有在給定程序中才能通路這兩種線程類型。

pthread_attr_setscope

文法

int pthread_attr_setscope(pthread_attr_t *tattr,int scope);

#include <pthread.h>
pthread_attr_t tattr;
int ret;
/* bound thread */
ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
/* unbound thread */
ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS); 
           

本示例使用三個函數調用:用于初始化屬性的調用、用于根據預設屬性設定所有變體

的調用,以及用于建立pthreads 的調用。

#include <pthread.h>
pthread_attr_t attr;
pthread_t tid;
void start_routine;
void arg;
int ret;

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
/* BOUND behavior */
ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
ret = pthread_create (&tid, &tattr, start_routine, arg); 
           

pthread_attr_setscope

傳回值

pthread_attr_setscope()

成功完成後将傳回零。其他任何傳回值都表示出現了錯誤。

如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 嘗試将tattr 設定為無效的值。

擷取範圍

請使用

pthread_attr_getscope(3C)

檢索線程範圍。

pthread_attr_getscope

文法

int pthread_attr_getscope(pthread_attr_t *tattr, int *scope);
           
#include <pthread.h>
pthread_attr_t tattr;
int scope;
int ret;

/* get scope of thread */
ret = pthread_attr_getscope(&tattr, &scope); 
           

pthread_attr_getscope

傳回值

pthread_attr_getscope()

成功完成後将傳回零。其他任何傳回值都表示出現了錯誤。

如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: scope 的值為NULL 或tattr 無效。

設定線程并行級别

針對标準符合性提供了

pthread_setconcurrency(3C)

。應用程式使用

pthread_setconcurrency()

通知系統其所需的并發級别。對于Solaris 9 發行版中引入的

線程實作,此接口沒有任何作用,所有可運作的線程都将被連接配接到LWP。

pthread_setconcurrency

文法

#include <pthread.h>
int pthread_setconcurrency(int new_level);
           

pthread_setconcurrency

傳回值

如果出現以下情況,

pthread_setconcurrency()

将失敗:

EINVAL

描述: new_level 指定的值為負數。

EAGAIN

描述: new_level 指定的值将導緻系統資源不足。

擷取線程并行級别

pthread_getconcurrency(3C)

傳回先前調用

pthread_setconcurrency()

時設定的值。

pthread_getconcurrency

文法

#include <pthread.h>

int pthread_getconcurrency(void); 
           

如果以前未調用

pthread_setconcurrency()

函數,則

pthread_getconcurrency()

将傳回

零。

pthread_getconcurrency

傳回值

pthread_getconcurrency()

始終會傳回先前調用

pthread_setconcurrency()

時設定的并

發級别。如果從未調用

pthread_setconcurrency()

,則

pthread_getconcurrency()

将返

回零。

設定排程政策

請使用

pthread_attr_setschedpolicy(3C)

設定排程政策。POSIX 标準指定

SCHED_FIFO

(先入先出)、

SCHED_RR

(循環)或

SCHED_OTHER(

實作定義的方法)的排程政策屬

性。

pthread_attr_setschedpolicy(3C)

文法

int pthread_attr_setschedpolicy(pthread_attr_t *tattr, int policy);
           
#include <pthread.h>
pthread_attr_t tattr;
int policy;
int ret; 

/* set the scheduling policy to SCHED_OTHER */
ret = pthread_attr_setschedpolicy(&tattr, SCHED_OTHER); 
           

SCHED_FIFO

如果調用程序具有有效的使用者ID 0,則争用範圍為系統(

PTHREAD_SCOPE_SYSTEM

) 的

先入先出線程屬于實時(RT) 排程類。如果這些線程未被優先級更高的線程搶占,則

會繼續處理該線程,直到該線程放棄或阻塞為止。對于具有程序争用範圍

(

PTHREAD_SCOPE_PROCESS

) 的線程或其調用程序沒有有效使用者ID 0 的線程,請使用

SCHED_FIFO

SCHED_FIFO

基于TS 排程類。

SCHED_RR

如果調用程序具有有效的使用者ID 0,則争用範圍為系統(

PTHREAD_SCOPE_SYSTEM

) 的

循環線程屬于實時(RT) 排程類。如果這些線程未被優先級更高的線程搶占,并且這

些線程沒有放棄或阻塞,則在系統确定的時間段内将一直執行這些線程。對于具有

程序争用範圍(

PTHREAD_SCOPE_PROCES

) 的線程,請使用

SCHED_RR

(基于TS 排程

類)。此外,這些線程的調用程序沒有有效的使用者ID 0。

SCHED_FIFO

SCHED_RR

在POSIX 标準中是可選的,而且僅用于實時線程。

pthread_attr_setschedpolicy

傳回值

pthread_attr_setschedpolicy()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下任一情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 嘗試将tattr 設定為無效的值。

ENOTSUP

描述: 嘗試将該屬性設定為不受支援的值。

擷取排程政策

請使用

pthread_attr_getschedpolicy(3C)

檢索排程政策。

pthread_attr_getschedpolicy

文法

int pthread_attr_getschedpolicy(pthread_attr_t *tattr, int *policy);
           
#include <pthread.h>
pthread_attr_t tattr;
int policy;
int ret;
/* get scheduling policy of thread */
ret = pthread_attr_getschedpolicy (&tattr, &policy); 
           

pthread_attr_getschedpolicy

傳回值

pthread_attr_getschedpolicy()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 參數policy 為NULL 或tattr 無效。

設定繼承的排程政策

請使用

pthread_attr_setinheritsched(3C)

設定繼承的排程政策。

pthread_attr_setinheritsched

文法

int pthread_attr_setinheritsched(pthread_attr_t *tattr, int inherit);
           
#include <pthread.h>
pthread_attr_t tattr;
int inherit;
int ret;
/* use the current scheduling policy */
ret = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED); 
           

inherit 值

PTHREAD_INHERIT_SCHED

表示建立的線程将繼承建立者線程中定義的排程策

略。将忽略在

pthread_create()

調用中定義的所有排程屬性。如果使用預設值

PTHREAD_EXPLICIT_SCHED

,則将使用

pthread_create()

調用中的屬性。

pthread_attr_setinheritsched

傳回值

pthread_attr_setinheritsched()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下任一情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 嘗試将tattr 設定為無效的值。

ENOTSUP

描述: 嘗試将屬性設定為不受支援的值。

擷取繼承的排程政策

pthread_attr_getinheritsched(3C)

将傳回由

pthread_attr_setinheritsched()

設定的

排程政策。

pthread_attr_getinheritsched

文法

int pthread_attr_getinheritsched(pthread_attr_t *tattr, int *inherit);
           
#include <pthread.h>
pthread_attr_t tattr;
int inherit;
int ret; 

/* get scheduling policy and priority of the creating thread */
ret = pthread_attr_getinheritsched (&tattr, &inherit); 
           

pthread_attr_getinheritsched

傳回值

pthread_attr_getinheritsched()

成功完成後将傳回零。其他任何傳回值都表示出現了

錯誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: 參數inherit 為NULL 或tattr 無效。

設定排程參數

pthread_attr_setschedparam(3C)

可以設定排程參數。

pthread_attr_setschedparam

文法

int pthread_attr_setschedparam(pthread_attr_t *tattr,
            const struct sched_param *param);
           
#include <pthread.h>
pthread_attr_t tattr;
int newprio;
sched_param param;
newprio = ; 

/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* set the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, &param); 
           

排程參數是在param 結構中定義的。僅支援優先級參數。新建立的線程使用此優先級運

行。

pthread_attr_setschedparam

傳回值

pthread_attr_setschedparam()

成功完成後将傳回零。其他任何傳回值都表示出現了錯

誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: param 的值為NULL 或tattr 無效。

可以采用兩種方式之一來管理pthreads 優先級:

■ 建立子線程之前,可以設定優先級屬性

■ 可以更改父線程的優先級,然後再将該優先級改回來

擷取排程參數

pthread_attr_getschedparam(3C)

将傳回由

pthread_attr_setschedparam()

定義的排程

參數。

pthread_attr_getschedparam

文法

int pthread_attr_getschedparam(pthread_attr_t *tattr,
                const struct sched_param *param);
           
#include <pthread.h>
pthread_attr_t attr;
struct sched_param param;
int ret; 

/* get the existing scheduling param */
ret = pthread_attr_getschedparam (&tattr, &param); 
           

使用指定的優先級建立線程

建立線程之前,可以設定優先級屬性。将使用在

sched_param

結構中指定的新優先級創

建子線程。此結構還包含其他排程資訊。

建立子線程時建議執行以下操作:

■ 擷取現有參數

■ 更改優先級

■ 建立子線程

■ 恢複原始優先級

建立具有優先級的線程的示例

示例2 給出了使用不同于其父線程優先級的優先級建立子線程的示例。

示例2建立具有優先級的線程

#include <pthread.h>
#include <sched.h>
pthread_attr_t tattr;
pthread_t tid;
int ret;
int newprio = ;
sched_param param; 

/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
/* safe to get existing scheduling param */
ret = pthread_attr_getschedparam (&tattr, &param);
/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* setting the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, &param);
/* with new priority specified */
ret = pthread_create (&tid, &tattr, func, arg); 
           

pthread_attr_getschedparam

傳回值

pthread_attr_getschedparam()

成功完成後将傳回零。其他任何傳回值都表示出現了錯

誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: param 的值為NULL 或tattr 無效。

設定棧大小

pthread_attr_setstacksize(3C)

可以設定線程棧大小。

pthread_attr_setstacksize

文法

int pthread_attr_setstacksize(pthread_attr_t *tattr,
                    size_t size);
           
#include <pthread.h>
pthread_attr_t tattr;
size_t size;
int ret; 
size = (PTHREAD_STACK_MIN + ); 

/* setting a new size */
ret = pthread_attr_setstacksize(&tattr, size); 
           

stacksize 屬性定義系統配置設定的棧大小(以位元組為機關)。size 不應小于系統定義的最小

棧大小

size 包含新線程使用的棧的位元組數。如果size 為零,則使用預設大小。在大多數情況

下,零值最适合。

PTHREAD_STACK_MIN

是啟動線程所需的棧空間量。此棧空間沒有考慮執行應用程式代碼

所需的線程例程要求。

pthread_attr_setstacksize

傳回值

pthread_attr_setstacksize()

成功完成後将傳回零。其他任何傳回值都表示出現了錯

誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: size 值小于

PTHREAD_STACK_MIN

,或超出了系統強加的限制,或者tattr 無效。

擷取棧大小

pthread_attr_getstacksize(3C)

将傳回由

pthread_attr_setstacksize()

設定的棧大

小。

pthread_attr_getstacksize

文法

int pthread_attr_getstacksize(pthread_attr_t *tattr,
                    size_t *size);
           
#include <pthread.h>
pthread_attr_t tattr;
size_t size;
int ret; 

/* getting the stack size */
ret = pthread_attr_getstacksize(&tattr, &size); 
           

pthread_attr_getstacksize

傳回值

pthread_attr_getstacksize()

成功完成後将傳回零。其他任何傳回值都表示出現了錯

誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: tattr 無效。

關于棧

通常,線程棧是從頁邊界開始的。任何指定的大小都被向上舍入到下一個頁邊界。不

具備通路權限的頁将被附加到棧的溢出端。大多數棧溢出都會導緻将

SIGSEGV

信号發送

到違例線程。将直接使用調用方配置設定的線程棧,而不進行修改。指定棧時,還應使用

PTHREAD_CREATE_JOINABLE

建立線程。在該線程的

pthread_join(3C)

調用傳回之前,不會釋放該棧。在該線程終止之前,不會釋放該線程的棧。

了解這類線程是否已終止的唯一可靠方式是使用

pthread_join(3C)

為線程配置設定棧空間

一般情況下,不需要為線程配置設定棧空間。系統會為每個線程的棧配置設定1MB(對于32 位

系統)或2MB(對于64 位系統)的虛拟記憶體,而不保留任何交換空間。系統将使用

mmap()

MAP_NORESERVE

選項來進行配置設定。

系統建立的每個線程棧都具有紅色區域。系統通過将頁附加到棧的溢出端來建立紅色

區域,進而捕獲棧溢出。此類頁無效,而且會導緻記憶體(通路時)故障。紅色區域将

被附加到所有自動配置設定的棧,無論大小是由應用程式指定,還是使用預設大小。

注– 對于庫調用和動态連結,運作時棧要求有所變化。應絕對确定,指定的棧滿足庫調

用和動态連結的運作時要求。

極少數情況下需要指定棧和/或棧大小。甚至專家也很難了解是否指定了正确的大小。

甚至符合ABI 标準的程式也不能靜态确定其棧大小。棧大小取決于執行中特定運作時

環境的需要。

生成自己的棧

指定線程棧大小時,必須考慮被調用函數以及每個要調用的後續函數的配置設定需求。需

要考慮的因素應包括調用序列需求、局部變量和資訊結構。

有時,您需要與預設棧略有不同的棧。典型的情況是,線程需要的棧大小大于預設棧

大小。而不太典型的情況是,預設大小太大。您可能正在使用不足的虛拟記憶體建立數

千個線程,進而處理數千個預設線程棧所需的數千兆位元組的棧空間。

對棧的最大大小的限制通常較為明顯,但對其最小大小的限制如何呢?必須存在足夠

的棧空間來處理推入棧的所有棧幀,及其局部變量等。

要擷取對棧大小的絕對最小限制,請調用宏

PTHREAD_STACK_MIN

PTHREAD_STACK_MIN

将針對執行NULL 過程的線程傳回所需的棧空間量。有用的線程所需的棧大小大于最小

棧大小,是以縮小棧大小時應非常謹慎。

#include <pthread.h>
pthread_attr_t tattr;
pthread_t tid;
int ret;
size_t size = PTHREAD_STACK_MIN + ; 

/* initialized with default attributes */
ret = pthread_attr_init(&tattr);
/* setting the size of the stack also */
ret = pthread_attr_setstacksize(&tattr, size);
/* only size specified in tattr*/
ret = pthread_create(&tid, &tattr, start_routine, arg); 
           

設定棧位址和大小

pthread_attr_setstack(3C)

可以設定線程棧位址和大小。

pthread_attr_setstack(3C)

文法

int pthread_attr_setstack(pthread_attr_t *tattr,void *stackaddr,
                        size_t stacksize);
           
#include <pthread.h>
pthread_attr_t tattr;
void *base;
size_t size;
int ret; 

base = (void *) malloc(PTHREAD_STACK_MIN + );
/* setting a new address and size */
ret = pthread_attr_setstack(&tattr, base,PTHREAD_STACK_MIN + ); 
           

stackaddr 屬性定義線程棧的基準(低位位址)。stacksize 屬性指定棧的大小。如果将

stackaddr 設定為非空值,而不是預設的NULL,則系統将在該位址初始化棧,假設大小

為stacksize。

base 包含新線程使用的棧的位址。如果base 為NULL,則

pthread_create(3C)

将為大小

至少為stacksize 位元組的新線程配置設定棧。

pthread_attr_setstack(3C)

傳回值

pthread_attr_setstack()

成功完成後将傳回零。其他任何傳回值都表示出現了錯誤。

如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: base 或tattr 的值不正确。stacksize 的值小于

PTHREAD_STACK_MIN

以下示例說明如何使用自定義棧位址和大小來建立線程。

#include <pthread.h>
pthread_attr_t tattr;
pthread_t tid;
int ret;
void *stackbase;
size_t size; 

/* initialized with default attributes */
ret = pthread_attr_init(&tattr);
/* setting the base address and size of the stack */
ret = pthread_attr_setstack(&tattr, stackbase,size);
/* address and size specified */
ret = pthread_create(&tid, &tattr, func, arg);
           

擷取棧位址和大小

pthread_attr_getstack(3C)

将傳回由

pthread_attr_setstack()

設定的線程棧位址和大

小。

pthread_attr_getstack

文法

int pthread_attr_getstack(pthread_attr_t *tattr,void * *stackaddr,
                    size_t *stacksize);
           
#include <pthread.h>
pthread_attr_t tattr;
void *base;
size_t size;
int ret; 

/* getting a stack address and size */
ret = pthread_attr_getstackaddr (&tattr, &base, &size); 
           

pthread_attr_getstack

傳回值

pthread_attr_getstackaddr()

成功完成後将傳回零。其他任何傳回值都表示出現了錯

誤。如果出現以下情況,該函數将失敗并傳回對應的值。

EINVAL

描述: tattr 的值不正确。

繼續閱讀