2014-10-05 19 views
5

Ich versuche, die Signalverarbeitung zwischen Prozessen und Threads zu lernen. Die Antwort auf ein paar Fragen würde mir helfen, es besser zu verstehen.Signalverarbeitung unter Pthreads

Ich weiß, dass ein Prozess ein Signal an die Prozessgruppe senden kann und mehrere Prozesse das gleiche Signal empfangen können, aber ich bin mir nicht sicher über Threads.

  • Können Signale, die an alle Pthreads gesendet werden, gleichzeitig von mehr als einem Pthread verarbeitet werden?

ich mein Setup-Programm alle Signale zu blockieren pthread_sigmask() mit, ich habe zwei Threads sigwait(SIGUSR1) verwenden, um Signale zu warten, und ich habe das Hauptthread SIGUSR1 Signale senden. Es scheint, dass alles gut funktioniert, wenn nur ein Thread die Signale verarbeitet (ich mache den Code in der anderen aus), aber wenn beide den Code ausführen, hängt er oder bricht zu schnell ab.

Der Code wird unten eingefügt.

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

Ich glaube, das Mantra ist "Signale werden gesendet, um zu verarbeiten" und wird einmal an einen Thread geliefert werden, der das Signal nicht ignoriert. –

+0

Ich bin relativ sicher, dass Signale an einen bestimmten Thread oder alle Threads gesendet werden können. Ich weiß nicht, ob nur einer damit umgehen kann, aber ich denke, sie alle können das Signal empfangen. – OwlsCIS

+0

@ 0d0a Signalhandler sind nicht relevant, wenn Sie die Signale blockieren und dann nach ihnen suchen. – o11c

Antwort

3
  • Kann Signale [werden], um alle pThreads gesendet [und] um mehr als ein pthread zugleich behandelt werden?

Nicht zur gleichen Zeit. Dies sind die Möglichkeiten:

  1. senden ein Signal an einen Prozess (kill()): In diesem Fall wird ein Thread für das Signal hören empfangen kann, aber nur wird man es tun.
  2. Ein Signal an eine Prozessgruppe senden: Das Signal wird an alle Prozesse in der Gruppe gesendet.
  3. Senden Sie ein Signal an einen bestimmten Thread (pthread_kill()): jetzt senden Sie es an eine bestimmte Thread-ID.

Vorbild:

int pthread_kill(pthread_t thread, int sig); 

In Ihrem Fall, ich glaube, der einzige Weg, um das Signal an alle Threads zu liefern ist entlang aller Thread-IDs Iterieren das Signal mit pthread_kill() zu senden.

+0

Das musste ich herausfinden. Vielen Dank! Ich habe ein paar Experimente durchgeführt und das gleiche herausgefunden, aber ich war mir nicht sicher, weil ich nicht sicher bin, was meinen Code betrifft. Das erklärt es. – OwlsCIS