2011-07-18 7 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グローバル変数を設定させ、sigsuspendの後にそのセットが返ってくるかどうかを調べることができます(もしそうでなければsigsuspendコールを繰り返すためにループします)。または、sigsuspendに渡されたマスクを設定して、すべてSYNC_SIGをブロックすることもできます。他のプロセスがあなたのプロセスに偽のSIGUSR1を送ると、これらのどちらもうまくいきませんが、意図的にあなたのプログラムを妨害しようとしている場合にのみ起こります。

+0

受信した信号を検証する良い方法はSYNC_SIGですか? – q0987

関連する問題