天天看點

Linux多線程程式設計(二)——線程屬性

pthread接口允許我們通過設定每個對象關聯的不同屬性來細調線程的行為。

在上一篇中我們調研pthread_create函數的執行個體中,傳入的參數都是空指針,而不是指向pthread_attr_t結構的指針。可以使用pthread_attr_t結構修改線程預設 屬性,并把這些屬性和建立的線程聯系起來。可以使用pthread_attr_init函數初始化pthread_attr_t。在調用pthread_attr_init以後,pthread_attr_t結構所包含的就是作業系統實作支援的所有線程屬性的預設值。

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t *attr);

			兩個函數的傳回值:若成功,傳回0;否則,傳回錯誤編号
           

如果要反初始化pthread_attr_t結構,可以調用pthread_attr_destroy函數。如果pthread_attr_init的實作對實作屬性對象的記憶體空間是 動态配置設定的,pthread_attr_destroy就會釋放該記憶體空間。除此之外,pthread_attr_destroy還會用無效的值初始化屬性對象,是以,如果該屬性對象被誤用,将會導緻pthread_create函數傳回錯誤代碼。

如果在建立線程時就知道不需要了解線程的終止狀态,就可以修改pthread_attr_t結構中的detachstate設定成以下兩個合法值之一:PTHREAD_CREATE_DETACHED,以分離狀态啟動線程;或者PTHREAD_CREATE_JOINABLE,正常啟動線程,應用程式可以擷取線程的終止狀态。

#include <pthread.h>

int pthread_attr_getdetachstate(const pthread_attr_t *restrict attr,
				int *detachstate);

int pthread_attr_setdetachstate(pthread_attr_t *attr, int *detachstate)

			兩個函數的傳回值:若成功,傳回0;否則,傳回錯誤編号
           

可以調用pthread_attr_getdetachstate函數 擷取目前的detachstate線程屬性。第二個參數所指向的整數要麼設定成PTHREAD_CREATE_DETACHED,要麼設定成PTHREAD_CREATE_JOINABLE,具體要取決于給定 pthread_attr_t結構中的屬性值。

可以使用函數pthread_attr_getstack和pthread_attr_setstack對線程棧屬性進行管理。

#include <pthread.h>

int pthread_attr_getstack(const pthread_attr_t *restrict attr,
			  void **restrict stackaddr,
			  size_t *restrict stacksize);

int pthread_attr_setstack(pthread_attr_t *attr,
			  void *stackaddr, size_t stacksize);

			兩個函數的傳回值:若成功,傳回0;否則,傳回錯誤編号
           

對于程序來說,虛位址空間的大小是固定的。因為程序中隻有一個棧,是以它的大小通常不是問題。但對于線程來說,同樣大小的虛位址空間必須被是以的線程棧共享。如果應用程式使用了許多線程,以緻這些線程棧的累計大小超過了可用的虛位址空間,就需要減少預設的線程棧大小。另一方面,如果線程調用的函數配置設定了大量的自動變量,或者調用的函數涉及許多很深的棧幀,那麼需要的棧大小可能要比預設的大。

如果線程的虛位址空間都用完了,那可以使用malloc或者mmap來為可替代的棧配置設定空間,并用pthread_attr_setstack函數來改變建立線程的棧位置。由stackaddr參數指定的位址可以用作線程棧的記憶體範圍中的最低可尋址位址,該位址與處理器結構相應的邊界應對其。當然,這要假設malloc和mmap所用的虛位址範圍與程式棧目前使用的虛位址範圍不同。

stackaddr線程屬性被定義為棧的最低記憶體位址,但這并不一定是棧的開始位址位置。對于一個給定的處理器結構來說,如果棧是從高位址向低位址方向增長的,那麼stackaddr線程屬性将是棧的結尾位置,而不是開始位置。

應用程式也可以通過pthread_attr_getstacksize和pthread_attr_setstacksize函數讀取或設定線程屬性stacksize。

#include <pthread.h>

int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
			      size_t *restrict stacksize);

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

			兩個函數的傳回值:若成功,傳回0;否則,傳回錯誤編号
           

如果希望改變預設的棧大小,但又不想自己處理線程棧的配置設定問題,這時使用pthread_attr_setstacksize函數就非常有用。設定stacksize屬性時,選擇的stacksize不能小于PTHREAD_STACK_MIN。

線程屬性guardsize控制着線程棧末尾之後用以避免棧溢出的擴充記憶體的大小。這個屬性預設值是有具體實作來定義的,但常用值是系統頁大小。可以把guardsize線程屬性設定為0,不允許屬性的這種特征行為發生:在這種情況下,不會提供警戒緩沖區。同樣,如果修改了線程屬性stackaddr,系統就認為我們将自己管理棧,進而使警戒緩沖區機制無效,這等同于把guardsize線程屬性設定為0.

#include <pthread.h>

int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
			      size_t *restrict guardsize);

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

			兩個函數的傳回值:若成功,傳回0;否則,傳回錯誤編号
           

如果guardsize線程屬性被修改來了,作業系統可能會把它取為頁大小的整數倍。如果線程的棧指針溢出到警戒區域,應用程式就可以通過信函接收到出錯資訊。

繼續閱讀