在信號部分提到一個可重入函數的概念,先回顧一下。可重入函數是可以在信號處理函數中調用的函數,未使用全局變量、靜態變量的函數。
線程這部分有個線程安全函數的概念,和可重入入函數類似。線程安全函數指的是可以在線程中被安全調用的函數,那什麼樣的函數會被線程不安全的調用呢?訪問了臨界資源的函數是不安全的。雖然全局、靜態變量是屬於臨界資源,但是這個概念又有別於不可重入函數,如果不安全的函數中對臨界區使用了同步的措施,那麼這個函數仍然是不可重入的函數,但已經是線程安全的了。
如果一個進程中的多個線程都使用了一個全局變量,那麼這個變量就成為了臨界資源,Posix線程庫中提供給我們一個讓同一個全局變量成為每個線程私有的變量的方法(如errno是一個全局變量,但每個線程都有自己的一個errno為私有的)。這個方法稱為線程的私有數據(對同一全局變量在每個線程的值不同),通過綁定鍵值實現,通過pthread_key_create()/pthread_key_delete()函數創建/刪除鍵,使用pthread_setspecific()綁定鍵值和全局變量,使用pthread_getspecific()獲取鍵值對應的私有全局變量的值。
[cpp] int pthread_key_create(pthread_key_t *key, void(*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_create(pthread_key_t *key, void(*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key); 信號是進程中的語義,那在線程中信號是怎樣處理的呢?之前說過,發送給進程的信號會送往進程中的某一個線程,在創建線程時會繼承信號屏蔽字但之後線程之間的信號屏蔽字就不互相影響了,但是我們之前學到的更改屏蔽字的函數sigprocmask()是改變整個進程(所有線程)的屏蔽字,那如何只更改某個線程的屏蔽字呢?使用pthread_sigmask()函數:
[cpp] int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);該函數的參數以及返回值和sigprocmask()是一樣的。在多線程編程中處理信號的經典措施是:指定一個專門的線程來處理指定的信號,而其它線程則屏蔽此信號。
如果說我們就像要向某個線程發送信號該怎麼處理呢(只能是同一進程中的線程間,因為線程id只在同一進程中有意義)?使用pthread_kill函數:
[cpp] int pthread_kill(pthread_t thread, int signo);
int pthread_kill(pthread_t thread, int signo);如果signo為0,則可用於測試線程是否存在。
還有一個sigwait()函數,該函數將當前線程阻塞,至未決信號集中有set中的信號,則獲取該信號放到signop中
[cpp] int sigwait(const sigset_t *set, int *signop);
int sigwait(const sigset_t *set, int *signop);