pthread属性使用(转)
生活随笔
收集整理的這篇文章主要介紹了
pthread属性使用(转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
只有 pthreads 使用屬性和取消功能。本章中介紹的 API 僅適用于 POSIX 線程。除此之外,Solaris 線程和 pthreads 的功能大致是相同的。有關相似和不同之處的更多信息,請參見第 8 章,Solaris 線程編程。
屬性對象
通過設置屬性,可以指定一種不同于缺省行為的行為。使用 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 */
PTHREAD_SCOPE_PROCESS
新線程與進程中的其他線程發生競爭。
detachstate
PTHREAD_CREATE_JOINABLE
線程退出后,保留完成狀態和線程 ID。
stackaddr
NULL
新線程具有系統分配的棧地址。
stacksize
0
新線程具有系統定義的棧大小。
priority
0
新線程的優先級為 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 的值無效。
設置分離狀態
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()。
無論是創建分離線程還是非分離線程,在所有線程都退出之前,進程不會退出。有關從 main() 提前退出而導致的進程終止的討論,請參見結束。?
注 –
如果未執行顯式同步來防止新創建的分離線程失敗,則在線程創建者從 pthread_create() 返回之前,可以將其線程 ID 重新分配給另一個新線程。
非分離線程在終止后,必須要有一個線程用 join 來等待它。否則,不會釋放該線程的資源以供新線程使用,而這通常會導致內存泄漏。因此,如果不希望線程被等待,請將該線程作為分離線程來創建。?
示例 3–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_PROCESS) 的線程,請使用 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 = 30;
/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* set the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);?
調度參數是在 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, ¶m);
使指定的優先級創建線程
創建線程之前,可以設置優先級屬性。將使用在 sched_param 結構中指定的新優先級創建子線程。此結構還包含其他調度信息。?
創建子線程時建議執行以下操作:
獲取現有參數
更改優先級
創建子線程
恢復原始優先級
創建具有優先級的線程的示例
示例 3–2 給出了使用不同于其父線程優先級的優先級創建子線程的示例。
示例 3–2 創建具有優先級的線程
#include <pthread.h>
#include <sched.h>
pthread_attr_t tattr;
pthread_t tid;
int ret;
int newprio = 20;
sched_param param;
/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
/* safe to get existing scheduling param */
ret = pthread_attr_getschedparam (&tattr, ¶m);
/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* setting the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);
/* 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 + 0x4000);
/* 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)。
為線程分配棧空間
一般情況下,不需要為線程分配棧空間。系統會為每個線程的棧分配 1 MB(對于 32 位系統)或 2 MB(對于 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 + 0x4000;
/* 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 + 0x4000);
/* setting a new address and size */
ret = pthread_attr_setstack(&tattr, base,PTHREAD_STACK_MIN + 0x4000);
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 的值不正確。
http://hi.baidu.com/wbh_mstar/blog/item/6cfa79f0e4fd067bdcc47440.html
屬性對象
通過設置屬性,可以指定一種不同于缺省行為的行為。使用 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);
scope ?PTHREAD_SCOPE_PROCESS
新線程與進程中的其他線程發生競爭。
detachstate
PTHREAD_CREATE_JOINABLE
線程退出后,保留完成狀態和線程 ID。
stackaddr
NULL
新線程具有系統分配的棧地址。
stacksize
0
新線程具有系統定義的棧大小。
priority
0
新線程的優先級為 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()。
無論是創建分離線程還是非分離線程,在所有線程都退出之前,進程不會退出。有關從 main() 提前退出而導致的進程終止的討論,請參見結束。?
注 –
如果未執行顯式同步來防止新創建的分離線程失敗,則在線程創建者從 pthread_create() 返回之前,可以將其線程 ID 重新分配給另一個新線程。
非分離線程在終止后,必須要有一個線程用 join 來等待它。否則,不會釋放該線程的資源以供新線程使用,而這通常會導致內存泄漏。因此,如果不希望線程被等待,請將該線程作為分離線程來創建。?
示例 3–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_PROCESS) 的線程,請使用 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 = 30;
/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* set the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);?
調度參數是在 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, ¶m);
使指定的優先級創建線程
創建線程之前,可以設置優先級屬性。將使用在 sched_param 結構中指定的新優先級創建子線程。此結構還包含其他調度信息。?
創建子線程時建議執行以下操作:
獲取現有參數
更改優先級
創建子線程
恢復原始優先級
創建具有優先級的線程的示例
示例 3–2 給出了使用不同于其父線程優先級的優先級創建子線程的示例。
示例 3–2 創建具有優先級的線程
#include <pthread.h>
#include <sched.h>
pthread_attr_t tattr;
pthread_t tid;
int ret;
int newprio = 20;
sched_param param;
/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
/* safe to get existing scheduling param */
ret = pthread_attr_getschedparam (&tattr, ¶m);
/* set the priority; others are unchanged */
param.sched_priority = newprio;
/* setting the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);
/* 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 + 0x4000);
/* 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)。
為線程分配棧空間
一般情況下,不需要為線程分配棧空間。系統會為每個線程的棧分配 1 MB(對于 32 位系統)或 2 MB(對于 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 + 0x4000;
/* 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 + 0x4000);
/* setting a new address and size */
ret = pthread_attr_setstack(&tattr, base,PTHREAD_STACK_MIN + 0x4000);
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 的值不正確。
http://hi.baidu.com/wbh_mstar/blog/item/6cfa79f0e4fd067bdcc47440.html
總結
以上是生活随笔為你收集整理的pthread属性使用(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CCNP备考记录
- 下一篇: Ubuntu ssh 服务开启方法