2014-10-05 40 views
5

我想了解進程和線程之間的信號處理。幾個問題的答案會幫助我更好地理解它。pthreads之間的信號處理

我知道一個進程可以發送一個信號給進程組,並允許多個進程接收相同的信號,但我不確定線程​​。

  • 發送給所有pthreads的信號是否可以同時由多個pthread處理?

設置我的計劃,以阻止使用pthread_sigmask()所有信號,我有兩個線程使用sigwait(SIGUSR1)等待信號,和我有主線程發送SIGUSR1信號。當只有一個線程處理信號時(我將其中的代碼註釋掉),似乎一切運行良好,但是當兩者都運行sigwait()代碼時,它會掛起或終止得太快。

代碼粘貼在下面。

sig_atomic_t signals = 0; 
sig_atomic_t sigusr1_signals = 0; 
sig_atomic_t sigusr2_signals = 0; 
sig_atomic_t count = 0; 
sig_atomic_t totalcount = 0; 

sigset_t globalset; 

int WAIT = 1;   /* false = 0, true = 1 */ 

static int SIGNALS_SENT = 0; 
static int SIGNALS_RECEIVED = 0; 

void *sig1handler1(void *argv); 

void *reporterhandler(void *argv); 

int random_number(int min, int max); 

int main(void) { 

    pthread_t threads[2]; /* create an array to store a number of threads */ 

    //int *p_status = &status; 
    sigfillset(&globalset); 
    pthread_sigmask(SIG_BLOCK, &globalset, NULL); 

    /* Generate signal handling threads */ 
    if (pthread_create(&threads[0], NULL, &sig1handler1, NULL) > 0) 
    { 
     printf("Thread creation failure!\n"); 
     return -1; 
    } 


    /* create reporting thread */ 
    if (pthread_create(&threads[1], NULL, &reporterhandler, NULL) > 0) 
    { 
     printf("Thread creation failure!\n"); 
     return -1; 
    } 

    /* Signal all threads to begin work concurrently */ 
    WAIT = 0; 

    int c = 0; 
    while(c < 100) 
    { 
     int value = random_number(1, 2); 
     if (value == 1) 
      kill(0, SIGUSR1); 
     else 
      kill(0, SIGUSR2); 

     SIGNALS_SENT++; 
     c++; 
     usleep(10000); 
    } 

    kill(0, SIGINT); 


    /* Wait for each thread to finish and join */ 
    int i = 0; 
    for(i = 0; i < 2; i++) 
    { 
     if (pthread_join(threads[i], NULL) > 0) 
     { 
      printf("Thread [%u] join failure!\n", (unsigned int)threads[i]); 
      return -1; 
     } 

     printf("THREAD [%u] returned.\n", (unsigned int)threads[i]); 
    } 

    printf("Parent Process [%d] exiting successfully.\n", getpid()); 
    return EXIT_SUCCESS; 
} 


void *sig1handler1(void *argv) 
{ 
    pthread_t tid = pthread_self(); 
    printf("THREAD[%u] sig1handler1: waiting for signal to do some work...\n", (unsigned int)tid); 

// sigset_t myset; 
// sigfillset(&myset); 
// sigdelset(&myset, SIGINT); 
// sigdelset(&myset, SIGUSR1); 
// pthread_sigmask(SIG_SETMASK, &myset, NULL); 

    /* Wait for a signal to start work */ 
    while (WAIT); 

    int sig; 
    int count = 0; 

    while(1) 
    { 
     sigwait(&globalset, &sig); 
     if (sig == SIGUSR1) 
     { 
      sigusr1_signals++; 
      signals++; 
      count++; 
      //printf("thread1: caught SIGUSR1 signal!\n"); 
     } 
     else if (sig == SIGINT) 
     { 
      printf("thread1: caught SIGINT signal, detected SIGUSR1 %d times, and terminating!\n", count);   pthread_exit(NULL); 
     } 
    } 

    //printf("THREAD[%u] sig1handler1: doing some work!\n", (unsigned int)tid); 
    //return (void *)EXIT_SUCCESS; 
    //return (void *)NULL; 
    pthread_exit(NULL); 
} 

void *reporterhandler(void *argv) 
{ 
    pthread_t tid = pthread_self(); 
    printf("THREAD[%u] reporter: waiting for signal to do some work...\n", (unsigned int)tid); 

    int sig; 
    int count = 0; 

// sigset_t myset; 
// sigfillset(&myset); 
// sigdelset(&myset, SIGINT); 
// sigdelset(&myset, SIGUSR1); 
// sigdelset(&myset, SIGUSR2); 
// pthread_sigmask(SIG_SETMASK, &myset, NULL); 

    /* Wait for a signal to start work */ 
    while (WAIT); 

    while(1) 
    { 
     sigwait(&globalset, &sig); 
     if (sig == SIGUSR1) 
     { 
      sigusr1_signals++; 
      signals++; 
      count++; 
      totalcount++; 
      SIGNALS_RECEIVED++; 
     } 
     else if (sig == SIGUSR2) 
     { 
      sigusr2_signals++; 
      signals++; 
      count++; 
      totalcount++; 
      SIGNALS_RECEIVED++; 
     } 
     else if (sig == SIGINT) 
     { 
      printf("Reporter: SIGUSR1 detected %d times\n", sigusr1_signals); 
      printf("Reporter: SIGUSR2 detected %d times\n", sigusr2_signals); 
      printf("Reporter: detected %d signals\n", totalcount); 
      printf("Reporter: SIGNALS_SENT %d \n", SIGNALS_SENT); 
      printf("Reporter: SIGNALS_REC %d \n", SIGNALS_RECEIVED); 
      pthread_exit(NULL); 
     } 

     /* Display Report after detecting 10 signals */ 
     if (count == 10) 
        sigusr1_signals, sigusr2_signals); 

      count = 0; 
     } 
    } 

    //printf("THREAD[%u] reporter: doing some work!\n", (unsigned int)tid); 
    pthread_exit(NULL); 
} 

int random_number(int min, int max) 
{ 
    if (min < max) 
    { 
     max = max + 1;  /* include the max value */ 
     return (rand() % (max - min)) + min; 
    } 

    return -1; 
} 
+0

我相信口頭禪是'信號被髮送到過程',並且會被傳遞給一個不會忽略信號的線程。 – 2014-10-05 00:26:10

+0

我相對確定信號可以發送到特定的線程或所有線程。我不知道是否只有一個人可以處理,但我認爲他們都可以收到信號。 – OwlsCIS 2014-10-05 00:31:05

+0

@ 0d0a信號處理程序在您阻塞信號並輪詢它們時不相關。 – o11c 2014-10-05 01:47:42

回答

3
  • 能信號[被]發送至[和]可以由多於一個的並行線程在同一時間處理的所有並行線程?

不是在同一時間。這些都是可能性:

  1. 發送信號的過程(kill()):在這種情況下,任何線程監聽信號,可以接收,但只有一個會做到這一點。
  2. 向進程組發送信號:信號將被傳送到組中的所有進程。
  3. 發送信號到特定線程(pthread_kill()):現在您將它發送到特定線程ID。

原型:

int pthread_kill(pthread_t thread, int sig); 

在你的情況,我認爲該信號傳遞給所有線程的唯一方法就是沿着所有的線程ID迭代與pthread_kill()發送信號。

+0

這是我需要找出。謝謝!我跑了一些實驗,發現了相同的東西,但我不確定,因爲我不確定涉及到我的代碼。這解釋了它。 – OwlsCIS 2014-10-05 23:56:49