2014-10-05 13 views
5

Tôi đang cố gắng tìm hiểu xử lý tín hiệu giữa các quy trình và chủ đề. Câu trả lời cho một vài câu hỏi sẽ giúp tôi hiểu rõ hơn.Xử lý tín hiệu giữa các pthreads

Tôi biết rằng một quá trình có thể gửi tín hiệu đến nhóm xử lý và cho phép nhiều quy trình nhận cùng một tín hiệu, nhưng tôi không chắc về chủ đề.

  • Tín hiệu có thể gửi cho tất cả các pthread được xử lý bởi nhiều hơn một pthread cùng một lúc?

Tôi thiết lập chương trình để chặn tất cả tín hiệu sử dụng pthread_sigmask(), tôi có hai chủ đề sử dụng sigwait(SIGUSR1) để chờ tín hiệu và tôi có chủ đề chính gửi tín hiệu SIGUSR1. Dường như tất cả mọi thứ hoạt động tốt khi chỉ có một thread đang xử lý các tín hiệu (tôi nhận xét mã trong khác), nhưng khi cả hai đang chạy mã sigwait() nó treo hoặc chấm dứt quá nhanh.

Mã được dán bên dưới.

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

Tôi tin rằng câu thần chú là 'tín hiệu được gửi để xử lý' và sẽ được gửi một lần đến một chuỗi không bỏ qua tín hiệu. –

+0

Tôi tương đối chắc chắn rằng các tín hiệu có thể được gửi đến một chủ đề cụ thể hoặc tất cả các chủ đề. Tôi không biết nếu chỉ có một người có thể xử lý nó, nhưng tôi nghĩ rằng tất cả họ đều có thể nhận được tín hiệu. Bộ xử lý tín hiệu – OwlsCIS

+0

@ 0d0a không liên quan khi bạn chặn các tín hiệu và sau đó thăm dò ý kiến ​​cho chúng. – o11c

Trả lời

3
  • thể tín hiệu [được] gửi đến tất cả pthreads [và] được xử lý bởi nhiều hơn một pthread cùng một lúc?

Không phải cùng một lúc. Đây là những khả năng:

  1. Gửi một tín hiệu đến một quá trình (kill()): Trong trường hợp này, bất kỳ chủ đề nghe cho tín hiệu có thể nhận được nó, nhưng chỉ cần ai sẽ làm điều đó.
  2. Gửi tín hiệu đến nhóm xử lý: Tín hiệu sẽ được gửi đến tất cả các quy trình trong nhóm.
  3. Gửi tín hiệu đến một chủ đề cụ thể (pthread_kill()): bây giờ bạn đang gửi nó đến một ID luồng cụ thể.

Prototype:

int pthread_kill(pthread_t thread, int sig); 

Trong trường hợp của bạn, tôi nghĩ rằng cách duy nhất để cung cấp những tín hiệu cho tất cả các chủ đề được lặp lại cùng tất cả id chủ đề của bạn để gửi các tín hiệu với pthread_kill().

+0

Đây là những gì tôi cần tìm hiểu. Cảm ơn bạn! Tôi chạy một số thí nghiệm và phát hiện ra điều tương tự, nhưng tôi không chắc chắn vì tôi không chắc chắn khi nói đến mã của tôi. Điều này giải thích nó. – OwlsCIS

Các vấn đề liên quan