2014-10-05 5 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

मेरा मानना ​​है कि मंत्र 'सिग्नल को प्रक्रिया में भेजा जाता है' और एक बार उस धागे पर पहुंचाया जाएगा जो सिग्नल को अनदेखा नहीं कर रहा है। –

+0

मुझे अपेक्षाकृत यकीन है कि संकेतों को एक विशिष्ट धागे या सभी धागे पर भेजा जा सकता है। मुझे नहीं पता कि केवल कोई इसे संभाल सकता है, लेकिन मुझे लगता है कि वे सभी सिग्नल प्राप्त कर सकते हैं। – OwlsCIS

+0

@ 0d0a सिग्नल हैंडलर प्रासंगिक नहीं हैं जब आप संकेतों को अवरुद्ध करते हैं और फिर उनके लिए मतदान करते हैं। – o11c

उत्तर

3
  • संकेतों सभी pthreads [और] एक ही समय में एक से अधिक pthread द्वारा नियंत्रित किया जा करने के लिए भेजा [जा] कर सकते हैं?

एक ही समय में नहीं। ये संभावनाएं हैं:

  1. एक प्रक्रिया (kill()) के लिए एक संकेत भेजें: इस मामले में, किसी भी धागा संकेत के लिए सुन इसे प्राप्त कर सकते हैं, लेकिन सिर्फ एक यह करना होगा।
  2. एक प्रक्रिया समूह को एक संकेत भेजें: सिग्नल समूह में सभी प्रक्रियाओं को वितरित किया जाएगा।
  3. एक विशिष्ट थ्रेड (pthread_kill()) पर एक संकेत भेजें: अब आप इसे एक विशिष्ट थ्रेड आईडी पर भेज रहे हैं।

प्रोटोटाइप:

int pthread_kill(pthread_t thread, int sig); 

आपके मामले में, मुझे लगता है कि सभी धागे को संकेत देने के लिए एक ही रास्ता अपने सभी धागा आईडी के साथ पुनरावृत्ति है pthread_kill() साथ संकेत भेजने के लिए।

+0

यही वह है जो मुझे खोजने के लिए जरूरी था। धन्यवाद! मैंने कुछ प्रयोग चलाए और एक ही चीज़ को पता चला, लेकिन मुझे यकीन नहीं था क्योंकि जब मैं अपने कोड की बात करता हूं तो मुझे निश्चित नहीं है। यह बताता है। – OwlsCIS

संबंधित मुद्दे