2014-10-05 2 views
5

프로세스와 스레드 간의 신호 처리를 배우려고합니다. 몇 가지 질문에 대한 답은 그것을 더 잘 이해하는 데 도움이 될 것입니다.pthread 간의 신호 처리

프로세스가 프로세스 그룹에 신호를 보내고 여러 프로세스가 동일한 신호를 수신 할 수 있음을 알고 있지만 스레드에 대해 확신하지 못합니다.

  • 모든 pthreads로 보낸 신호를 동시에 둘 이상의 pthread에서 처리 할 수 ​​있습니까?

I 설치 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())로 신호 보내기 : 이제 특정 스레드 ID로 신호를 보냅니다.

은 프로토 타입 : 귀하의 경우

int pthread_kill(pthread_t thread, int sig); 

, 나는 모든 스레드에 신호를 제공 할 수있는 유일한 방법은 pthread_kill()로 신호를 전송하는 모든 스레드 식별자를 따라 반복 생각합니다.

+0

이것이 내가 알아야 할 필요가있는 것입니다. 고맙습니다! 몇 가지 실험을 실행하여 같은 것을 발견했지만 내 코드와 관련하여 확실하지 않기 때문에 확실하지 않았습니다. 이것은 그것을 설명합니다. – OwlsCIS