pthread_sigmask 等控制執行緒的訊號掩碼
示例1:
-
/* 示例一:遮蔽訊號SIGINT
-
來源:http://www.leoox.com/?p=321
-
編譯:gcc pthread_sigmask1.c -lpthread
-
執行後,你發現你按下CTRL+C(觸發SIGINT訊號),這個程式根本停不下來。因為SIGINT訊號已經如我們所願被遮蔽掉了。
-
*/
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <sys/signal.h>
-
#include <string.h>
-
int main(int argc, char** argv)
-
{
-
pthread_t tid = pthread_self();
-
sigset_t mask;
-
sigemptyset(&mask);
-
sigaddset(&mask, SIGINT);
-
pthread_sigmask(SIG_SETMASK, &mask, NULL);//SIG_BLOCK SIG_SETMASK 會遮蔽掉SIGINT,但SIG_UNBLOCK不會遮蔽SIGINT
-
printf("[main][%lu] working hard ...\n", tid);
-
sleep(60);
-
printf("[main][%lu] good bye and good luck!\n", tid);
-
return 0;
-
}
示例二:主程序創建出來的執行緒將繼承主程序的掩碼
-
/* 示例二:主程序創建出來的執行緒將繼承主程序的掩碼
-
來源:http://www.leoox.com/?p=321
-
編譯:gcc pthread_sigmask2.c -lpthread
-
執行後,你可以發現,子執行緒果然接收不到pthread_kill傳送給自己的SIGINT訊號,
-
但可以收到SIGUSR1訊號!本來要休眠300s,但是收到了SIGUSR1訊號,
-
才休眠5秒就(提前294秒)醒來say goodbye了。
-
執行結果:
-
[[email protected] thread]$ ./a.out
-
[main][139999919077120] working hard ...
-
>>> Thread[139999919068928] Running ......
-
[main][139999919077120] send signal SIGINT ...
-
Thread[139999919068928] catch signo = 10
-
Thread[139999919068928] waitup(294), and say good bye!
-
[main][139999919077120] good bye and good luck!
-
[[email protected] thread]$
-
*/
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <sys/signal.h>
-
#include <string.h>
-
void handler(int signo)
-
{
-
pthread_t tid = pthread_self();
-
printf("Thread[%lu] catch signo = %d\n", tid, signo);
-
return;
-
}
-
void* run(void *param)
-
{
-
pthread_t tid = pthread_self();
-
printf(">>> Thread[%lu] Running ......\n", tid);
-
int rc = sleep(300);
-
printf("Thread[%lu] waitup(%d), and say good bye!\n", tid, rc);
-
return NULL;
-
}
-
int main(int argc, char** argv)
-
{
-
int ret = 0, i = 0;
-
pthread_t tid = pthread_self();
-
/* 註冊SIGUSR1訊號處理函式 */
-
struct sigaction sa;
-
memset(&sa, 0, sizeof(sa));
-
sigemptyset(&sa.sa_mask);
-
sa.sa_flags = 0;
-
sa.sa_handler = handler;
-
sigaction(SIGUSR1, &sa, NULL);
-
/* 遮蔽訊號SIGINT */
-
sigset_t mask;
-
sigemptyset(&mask);
-
sigaddset(&mask, SIGINT);
-
pthread_sigmask(SIG_BLOCK, &mask, NULL);
-
pthread_t threads[2];
-
pthread_create(&threads[0], NULL, run, NULL);
-
printf("[main][%lu] working hard ...\n", tid);
-
sleep(1);
-
/* 主程序創建出來的執行緒將繼承主程序的掩碼。所以子執行緒收不到SIGINT訊號。 */
-
pthread_kill(threads[0], SIGINT);
-
printf("[main][%lu] send signal SIGINT ...\n", tid);
-
sleep(5);
-
/* 子執行緒可以收到SIGUSR1訊號。 */
-
pthread_kill(threads[0], SIGUSR1);
-
pthread_join(threads[0], NULL);
-
sleep(1);
-
printf("[main][%lu] good bye and good luck!\n", tid);
-
return 0;
-
}
示例三:子執行緒可以後天培養自己對訊號的喜好
-
/* 示例三:子執行緒可以後天培養自己對訊號的喜好
-
來源:http://www.leoox.com/?p=321
-
編譯:gcc pthread_sigmask3.c -lpthread
-
子執行緒天生繼承了主執行緒對訊號的喜好,但是自己可以通過後天的努力改變。
-
比如主執行緒喜歡SIGUSR1訊號,但是子執行緒可以不喜歡它,遮蔽掉SIGUSR1訊號。
-
由此可見,linux裡的每個執行緒有自己的訊號掩碼,所以使用pthread_kill給指定執行緒傳送訊號時,
-
一定謹慎設定好執行緒的訊號掩碼。
-
當然,用kill傳送訊號,在多執行緒環境下,kill所產生的訊號時傳遞到整個程序的,
-
並且所有執行緒都有機會收到這個訊號,但具體是哪個執行緒處理這個訊號,就不一定。
-
一般情況下,都是主執行緒處理這個訊號。
-
執行結果:
-
[[email protected] thread]$ gcc pthread_sigmask3.c -lpthread
-
[[email protected] thread]$ ./a.out
-
[main][140613382825728] working hard ...
-
>>> [1481543657]Thread[140613382817536] Running ......
-
[main][140613382825728] send signal SIGUSR1 ...
-
[1481543841]Thread[140613382825728] catch signo = 10 ... //子執行緒sleep期間,kill -SIGUSR1 2839
-
[1481543861]Thread[140613382825728] catch signo = 10 ... done
-
[1481543957]Thread[140613382817536] waitup(0), and say good bye!
-
[main][140613382825728] good bye and good luck!
-
[[email protected] thread]$
-
*/
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <sys/signal.h>
-
#include <string.h>
-
void handler(int signo)
-
{
-
pthread_t tid = pthread_self();
-
printf("[%u]Thread[%lu] catch signo = %d ...\n", time(NULL), tid, signo);
-
sleep(20);
-
printf("[%u]Thread[%lu] catch signo = %d ... done\n", time(NULL), tid, signo);
-
return;
-
}
-
void* run(void *param)
-
{
-
pthread_t tid = pthread_self();
-
sigset_t mask;
-
#if 1
-
/* 這種情況下,本執行緒遮蔽所有的訊號 */
-
sigfillset(&mask);
-
#endif
-
#if 0
-
/* 這種情況下,本執行緒不遮蔽任何訊號 */
-
sigemptyset(&mask);
-
#endif
-
#if 0
-
/* 這種情況,本執行緒遮蔽以下的指定訊號 */
-
sigemptyset(&mask);
-
sigaddset(&mask, SIGINT);
-
sigaddset(&mask, SIGQUIT);
-
sigaddset(&mask, SIGHUP);
-
sigaddset(&mask, SIGTERM);
-
#endif
-
pthread_sigmask(SIG_SETMASK, &mask, NULL);
-
printf(">>> [%u]Thread[%lu] Running ......\n", time(NULL), tid);
-
int rc = sleep(300);
-
printf("[%u]Thread[%lu] waitup(%d), and say good bye!\n", time(NULL), tid, rc);
-
return NULL;
-
}
-
int main(int argc, char** argv)
-
{
-
pthread_t tid = pthread_self();
-
/* 註冊SIGUSR1訊號處理函式 */
-
struct sigaction sa;
-
memset(&sa, 0, sizeof(sa));
-
sigemptyset(&sa.sa_mask);
-
sa.sa_flags = 0;
-
sa.sa_handler = handler;
-
sigaction(SIGUSR1, &sa, NULL);
-
pthread_t threads[1];
-
pthread_create(&threads[0], NULL, run, NULL);
-
printf("[main][%lu] working hard ...\n", tid);
-
sleep(5);
-
/* 子執行緒遮蔽了SIGUSR1訊號,所以子執行緒收不到SIGUSR1訊號。 */
-
pthread_kill(threads[0], SIGUSR1);
-
printf("[main][%lu] send signal SIGUSR1 ...\n", tid);
-
sleep(5);
-
pthread_join(threads[0], NULL);
-
sleep(1);
-
printf("[main][%lu] good bye and good luck!\n", tid);
-
return 0;
-
}
示例四:主執行緒收到訊號,沒處理完,又來一個訊號,子執行緒會處理嗎? 會!
-
/* 示例四:主執行緒收到訊號,沒處理完,又來一個訊號,子執行緒會處理嗎? 會!
-
來源:http://www.leoox.com/?p=321
-
編譯:gcc pthread_sigmask4.c -lpthread
-
在一個命令列終端啟動a.out,在另一個命令列終端傳送4次SIGUSR1訊號給a.out程序
-
執行結果:
-
[[email protected] thread]$ ./a.out
-
[main][139796483913472] working hard ...
-
>>> [1481545031]Thread[139796483905280] Running ...... //此時傳送四次kill -SIGUSR1 2886,2886為a.out的程序號
-
[1481545054]Thread[139796483913472] catch signo = 10 ...
-
[1481545055]Thread[139796483905280] catch signo = 10 ...
-
[1481545056]Thread[139796483913472] catch signo = 10 ... done
-
[1481545056]Thread[139796483913472] catch signo = 10 ...
-
[1481545057]Thread[139796483905280] catch signo = 10 ... done
-
[1481545057]Thread[139796483905280] catch signo = 10 ...
-
[1481545058]Thread[139796483913472] catch signo = 10 ... done
-
[1481545059]Thread[139796483905280] catch signo = 10 ... done
-
>>> [1481545059]Thread[139796483905280] waitup(35), and say good bye!
-
[main][139796483913472] good bye and good luck!
-
[[email protected] thread]$
-
*/
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <sys/signal.h>
-
#include <string.h>
-
void handler(int signo)
-
{
-
pthread_t tid = pthread_self();
-
printf("[%u]Thread[%lu] catch signo = %d ...\n", time(NULL), tid, signo);
-
/*
-
* 訊號處理函式休眠2秒,這期間再發送同一個訊號,觀察子執行緒的表現。
-
*/
-
sleep(2);
-
printf("[%u]Thread[%lu] catch signo = %d ... done\n", time(NULL), tid, signo);
-
return;
-
}
-
void* run(void *param)
-
{
-
pthread_t tid = pthread_self();
-
printf(">>> [%u]Thread[%lu] Running ......\n", time(NULL), tid);
-
int rc = sleep(60);
-
printf(">>> [%u]Thread[%lu] waitup(%d), and say good bye!\n", time(NULL), tid, rc);
-
return NULL;
-
}
-
int main(int argc, char** argv)
-
{
-
pthread_t tid = pthread_self();
-
/* 註冊SIGUSR1訊號處理函式 */
-
struct sigaction sa;
-
memset(&sa, 0, sizeof(sa));
-
sigemptyset(&sa.sa_mask);
-
sa.sa_flags = 0;
-
sa.sa_handler = handler;
-
sigaction(SIGUSR1, &sa, NULL);
-
pthread_t threads[1];
-
pthread_create(&threads[0], NULL, run, NULL);
-
printf("[main][%lu] working hard ...\n", tid);
-
pthread_join(threads[0], NULL);
-
sleep(1);
-
printf("[main][%lu] good bye and good luck!\n", tid);
-
return 0;
-
}
如果把void handler(int signo)函式中的sleep(2)註釋掉,執行結果如下:
[[email protected] thread]$ ./a.out [main][140353429055232] working hard ... >>> [1481596389]Thread[140353429047040] Running ...... //此處傳送6次“kill -SIGUSR1 3123” [1481596401]Thread[140353429055232] catch signo = 10 ... [1481596401]Thread[140353429055232] catch signo = 10 ... done [1481596401]Thread[140353429055232] catch signo = 10 ... [1481596401]Thread[140353429055232] catch signo = 10 ... done [1481596402]Thread[140353429055232] catch signo = 10 ... [1481596402]Thread[140353429055232] catch signo = 10 ... done [1481596402]Thread[140353429055232] catch signo = 10 ... [1481596402]Thread[140353429055232] catch signo = 10 ... done [1481596402]Thread[140353429055232] catch signo = 10 ... [1481596402]Thread[140353429055232] catch signo = 10 ... done [1481596403]Thread[140353429055232] catch signo = 10 ... [1481596403]Thread[140353429055232] catch signo = 10 ... done >>> [1481596449]Thread[140353429047040] waitup(0), and say good bye! [main][140353429055232] good bye and good luck! [[email protected] thread]$ 可見,若子執行緒“沒空”(在sleep),主執行緒有空,訊號都給主執行緒處理了。