一 多線程信號
首先,信號的傳遞是根據情況而定的:
- 如果是異常產生的信號(比如程序錯誤,像SIGPIPE、SIGEGV這些),一般由系統發送,則只有產生異常的線程收到並處理。
- 如果是用
pthread_kill
產生的內部信號,則只有pthread_kill
參數中指定的目標線程收到並處理。 - 如果是外部進程使用
kill
產生的信號,通常是SIGINT、SIGHUP等job control信號,則會遍歷所有線程,直到找到一個不阻塞該信號的線程,然後調用它來處理。(一般從主線程找起),注意只有一個線程能收到。
其次,每個線程都有自己獨立的signal mask
,但所有線程共享進程的signal action
。這意味着,你可以在線程中調用pthread_sigmask
(不是sigmask
)來決定本線程阻塞哪些信號。但你不能調用sigaction
來指定單個線程的信號處理方式。如果在某個線程中調用了sigaction
處理某個信號,那麼這個進程中的未阻塞這個信號的線程在收到這個信號都會按同一種方式處理這個信號。另外,注意子線程的mask
是會從主線程繼承而來的。
二 信號處理
向指定ID的線程發送sig信號,如果線程代碼內不做處理,則按照信號默認的行爲影響整個進程,也就是說,如果你給一個線程發送了SIGQUIT,但線程卻沒有實現signal處理函數,則整個進程退出。
pthread_kill(threadid, SIGKILL)也一樣,殺死整個進程。如果要獲得正確的行爲,就需要在線程內實現signal(SIGKILL,sig_handler)了。
所以,如果int sig的參數不是0,那一定要清楚到底要幹什麼,而且一定要實現線程的信號處理函數,否則,就會影響整個進程。
OK,如果int sig是0呢,這是一個保留信號,一個作用是用來判斷線程是不是還活着。
我們來看一下pthread_kill的返回值:
成功:0
線程不存在:ESRCH
信號不合法:EINVAL
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
void *func1()/*1秒鐘之後退出*/
{
sleep(1);
printf("線程1(ID:0x%x)退出。/n",(unsigned int)pthread_self());
pthread_exit((void *)0);
}
void *func2()/*5秒鐘之後退出*/
{
sleep(5);
printf("線程2(ID:0x%x)退出。/n",(unsigned int)pthread_self());
pthread_exit((void *)0);
}
void test_pthread(pthread_t tid) /*pthread_kill的返回值:成功(0) 線程不存在(ESRCH) 信號不合法(EINVAL)*/
{
int pthread_kill_err;
pthread_kill_err = pthread_kill(tid,0);
if(pthread_kill_err == ESRCH)
printf("ID爲0x%x的線程不存在或者已經退出。/n",(unsigned int)tid);
else if(pthread_kill_err == EINVAL)
printf("發送信號非法。/n");
else
printf("ID爲0x%x的線程目前仍然存活。/n",(unsigned int)tid);
}
int main()
{
int ret;
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,func1,NULL);
pthread_create(&tid2,NULL,func2,NULL);
sleep(3);/*創建兩個進程3秒鐘之後,分別測試一下它們是否還活着*/
test_pthread(tid1);/*測試ID爲tid1的線程是否存在*/
test_pthread(tid2);/*測試ID爲tid2的線程是否存在*/
exit(0);
}