2011-07-18 1 views
1

На основе этого http://man7.org/tlpi/code/online/dist/procexec/fork_sig_sync.c.htmlКак родительский процесс действует посланный сигнал по дочернему процессу

/* fork_sig_sync.c 

    Demonstrate how signals can be used to synchronize the actions 
    of a parent and child process. 
*/ 
#include <signal.h> 
#include "curr_time.h"     /* Declaration of currTime() */ 
#include "tlpi_hdr.h" 

#define SYNC_SIG SIGUSR1    /* Synchronization signal */ 

static void    /* Signal handler - does nothing but return */ 
handler(int sig) 
{ 
} 

int 
main(int argc, char *argv[]) 
{ 
    pid_t childPid; 
    sigset_t blockMask, origMask, emptyMask; 
    struct sigaction sa; 

    setbuf(stdout, NULL);    /* Disable buffering of stdout */ 

    sigemptyset(&blockMask); 
    sigaddset(&blockMask, SYNC_SIG); /* Block signal */ 
    if (sigprocmask(SIG_BLOCK, &blockMask, &origMask) == -1) 
     errExit("sigprocmask"); 

    sigemptyset(&sa.sa_mask); 
    sa.sa_flags = SA_RESTART; 
    sa.sa_handler = handler; 
    if (sigaction(SYNC_SIG, &sa, NULL) == -1) 
     errExit("sigaction"); 

    switch (childPid = fork()) { 
    case -1: 
     errExit("fork"); 

    case 0: /* Child */ 

     /* Child does some required action here... */ 

     printf("[%s %ld] Child started - doing some work\n", 
       currTime("%T"), (long) getpid()); 
     sleep(2);    /* Simulate time spent doing some work */ 

     /* And then signals parent that it's done */ 

     printf("[%s %ld] Child about to signal parent\n", 
       currTime("%T"), (long) getpid()); 
     if (kill(getppid(), SYNC_SIG) == -1) 
      errExit("kill"); 

     /* Now child can do other things... */ 

     _exit(EXIT_SUCCESS); 

    default: /* Parent */ 

     /* Parent may do some work here, and then waits for child to 
      complete the required action */ 

     printf("[%s %ld] Parent about to wait for signal\n", 
       currTime("%T"), (long) getpid()); 
     sigemptyset(&emptyMask); 
     if (sigsuspend(&emptyMask) == -1 && errno != EINTR) // <<<<< Question 
      errExit("sigsuspend"); 
     printf("[%s %ld] Parent got signal\n", currTime("%T"), (long) getpid()); 

     /* If required, return signal mask to its original state */ 

     if (sigprocmask(SIG_SETMASK, &origMask, NULL) == -1) 
      errExit("sigprocmask"); 

     /* Parent carries on to do other things... */ 

     exit(EXIT_SUCCESS); 
    } 
} 

Вопрос

Когда родительский процесс вызывает sigsuspend, почему он не проверяет, что послал сигнал SYNC_SIG?

http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigsuspend.html

+0

В общем случае сигналы являются ужасным механизмом синхронизации между процессами. Я бы просто забыл об использовании сигналов для этого. Самый простой способ синхронизации между процессами - это каналы. Между нитями в одном и том же процессе используйте барьеры или семафоры. –

+0

Как новичок в этой теме, вопрос здесь заключается в понимании этого кода, а не в определении того, что является лучшим способом для выполнения этой задачи. – q0987

+0

Да, я написал как комментарий, а не ответ, потому что знал, что я должен был сказать, на самом деле не ответил на ваш вопрос. Я случайно просмотрел код и не сразу понял, что случилось, но я подозреваю, что это небольшая деталь. –

ответ

0

Код предполагает никакой другой сигнал не будет происходить в то время как программа работает, так что это не мешает проверить, что он получил правильный. Это означает, что при возникновении любого другого сигнала программа может выйти из строя.

добавить

Есть несколько способов, чтобы проверить, что правый сигнал посылается. Вы можете заставить обработчик установить sig_atomic_t глобальный var и проверить, что его набор после возврата sigsuspend (цикл, чтобы повторить вызов sigsuspend, если это не так). Или вы можете установить маску, переданную в sigsuspend, чтобы заблокировать все EXCEPT SYNC_SIG. Ни один из них не будет работать, если какой-либо другой процесс отправит ложный SIGUSR1 в ваш процесс, но это произойдет только в том случае, если кто-то намеренно пытается саботировать вашу программу.

+0

Можете ли вы сказать мне, что является хорошим методом для проверки принятого сигнала SYNC_SIG? – q0987