二 Pthread 并發編程( 三 )

上面的程序的輸出結果如下所示:
================In mainstack frame: rsp = 0x7ffc47096d50 rbp = 0x7ffc47096d80 rip = 0x4006c6================In funcstack frame: rsp = 0x7f0a60d43ee0 rbp = 0x7f0a60d43ef0 rip = 0x400634從上面的結果來看主線程和線程 t 執行的是不同的函數 , 而且兩個函數的棧幀差距還是很大的,我們計算一下 0x7ffc47096d80 - 0x7f0a60d43ef0 = 1038949363344 = 968G 的內存,因此很明顯這兩個線程使用的是不同的棧幀 。
線程的線程號在 pthread 當中的一個線程對應一個內核的線程,內核和 pthread 都給線程維護了一個線程的 id 號,我們可以使用 gettid 獲取操作系統給我們維護的線程號,使用函數 pthread_self 得到 pthread 線程庫給我們維護的線程號!
#define _GNU_SOURCE#include <stdio.h>#include <unistd.h>#include <pthread.h>#include <sys/types.h>void* func(void* arg) {  printf("pthread id = %ld tid = %d\n", pthread_self(), (int)gettid());  return NULL;}int main() {  pthread_t t;  pthread_create(&t, NULL, func, NULL);  pthread_join(t, NULL);  return 0;}上面的程序的輸出結果如下:
pthread id = 140063790135040 tid = 161643線程與信號在 pthread 庫當中主要給我們提供了一些函數用于信號處理,我們在 pthread 庫當中可以通過函數 pthread_kill 給其他的進程發送信號 。
 1) SIGHUP  2) SIGINT  3) SIGQUIT  4) SIGILL  5) SIGTRAP 6) SIGABRT  7) SIGBUS  8) SIGFPE  9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+338) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-758) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX我們可以在一個線程當中響應其他線程發送過來的信號,并且響應信號處理函數,在使用具體的例子深入了解線程的信號機制之前,首先我們需要了解到的是在 pthread 多線程的程序當中所有線程是共享信號處理函數的 , 如果在一個線程當中修改了信號處理函數,這個結果是會影響其他線程的 。
#define _GNU_SOURCE#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <signal.h>#include <string.h>void sig(int signo) {  char s[1024];  sprintf(s, "signo = %d tid = %d pthread tid = %ld\n", signo, gettid(), pthread_self());  write(STDOUT_FILENO, s, strlen(s));}void* func(void* arg) {  printf("pthread tid = %ld\n", pthread_self());  for(;;);  return NULL;}int main() {  signal(SIGHUP, sig);  signal(SIGTERM, sig);  signal(SIGSEGV, sig);  pthread_t t;  pthread_create(&t, NULL, func, NULL);  sleep(1);  pthread_kill(t, SIGHUP);  sleep(1);  return 0;}上面的程序的輸出結果如下所示:
pthread tid = 140571386894080signo = 1 tid = 7785 pthread tid = 140571386894080在上面的程序當中,我們首先在主函數里面重新定義了幾個信號的處理函數 , 將 SIGHUP、SIGTERM 和 SIGSEGV 信號的處理函數全部聲明為函數 sig,進程當中的線程接受到這個信號的時候就會調用對應的處理函數,在上面的程序當中主線程會給線程 t 發送一個 SIGHUP 信號,根據前面信號和數據對應關系我們可以知道 SIGHUP 對應的信號的數字等于 1 ,我們在信號處理函數當中確實得到了這個信號 。

推薦閱讀