2008-08-29 28 views
1

自然な番号を印刷する必要があります。 1,2、... nのように、親プロセスがすべての奇数を出力し、子プロセスがすべて偶数を出力するようにします。このすべては、POSIX信号を使用して行う必要があります。これを達成するにはどうすればいいですか?信号を使用して奇数 - 偶数を印刷する

出力は次のようになります。

親:1
子供:2
親:3
...

答えて

3

私はこの宿題は、あなたは多くのことをしようとするために、あなたに与えられたと思いますあなた自身が結論するのは、シグナルが良い同期技術ではありません

この貴重な教訓は、それをよく覚えて、今からセマフォを使用してください! :)

4

おそらく、あなたがこれまで持っているものを提供するために、より有益であろうと期待どおりに動作しませんか説明が、ここで私が思い付いたものです:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <signal.h> 
#include <stdlib.h> 

#define READY_SIGNAL SIGUSR1 

/* The ready flag is set when READY_SIGNAL is received. 
* It is needed so that when we wake up from sigsuspend 
* we know whether or not the signal received was READY_SIGNAL. */ 
volatile sig_atomic_t ready; 
void make_ready(int i) { ready = 1; } 

int 
main (int argc, char *argv[]) 
{ 
    pid_t cpid, ppid; /* pids of the child and parent */ 
    /* Signal masks for sigprocmask and sigsuspend */ 
    sigset_t block_mask, wait_mask; 
    unsigned long c = 1; /* The counter */ 
    unsigned long n = 100; /* The default max count value */ 
    struct sigaction act; 

    /* Override the default max count if provided */ 
    if (argv[1]) 
    n = strtoul(argv[1], NULL, 10); 

    /* Prepare signal masks */ 
    sigemptyset(&wait_mask); 
    sigemptyset(&block_mask); 
    sigaddset(&block_mask, READY_SIGNAL); 

    /* Set the signal mask for the parent to ignore READY_SIGNAL until 
    * we are ready to receive it, the mask will be inherited by the child, 
    * needed to avoid race conditions */ 
    sigprocmask(SIG_BLOCK, &block_mask, NULL); 

    /* Register the signal handler, will be inherited by the child */ 
    act.sa_flags = 0; 
    act.sa_handler = make_ready; 
    sigemptyset(&act.sa_mask); 
    sigaction(READY_SIGNAL, &act, NULL); 

    /* Get the parent's process id, needed for the child to send signals 
    * to the parent process, could alternatively use getppid in the child */ 
    ppid = getpid(); 

    /* Call fork, storing the child's process id needed for the parent to 
    * send signals to the child */ 
    cpid = fork(); 

    if (cpid < 0) { 
    perror("Fork failed"); 
    exit(EXIT_FAILURE); 
    } 

    if (cpid == 0) { 
    /* Child */ 
    c = 2; /* Child's first number will always be 2 */ 
    if (c > n) exit(0); /* If c > n we have nothing to do */ 

    do { 
     /* Suspend until we receive READY_SIGNAL */ 
     while (!ready) sigsuspend(&wait_mask); 

     /* Print out number, flush for proper output sequencing when output 
     is not a terminal. */ 
     printf("Child: %lu\n", c); 
     fflush(stdout); 

     ready = 0; /* Reset ready flag */ 
     c += 2; /* Increment counter */ 

     /* Wake up parent process */ 
     kill(ppid, READY_SIGNAL); 
    } while (c <= n); 
    } else { 
    /* Parent */ 
    for (;;) { 
     /* Print out number, flush for proper output sequencing when output 
     is not a terminal. */ 
     printf("Parent: %lu\n", c); 
     fflush(stdout); 

     c += 2; /* Increment counter */ 

     kill(cpid, READY_SIGNAL); /* Wake up child process */ 

     if (c > n) break; /* Don't go back to sleep if we are done */ 

     ready = 0; /* Reset ready flag */ 

     /* Suspend until we receive READY_SIGNAL */ 
     while (!ready) sigsuspend(&wait_mask); 
    }; 

    wait4(cpid, NULL, 0); /* Don't exist before child finishes */ 
    } 

    return 0; 
} 

これは、これらの基本的なテストに合格します:

./print_with_signals 100000|sort -n -k 2 -c && echo "Success"
./print_with_signals 100001|sort -n -k 2 -c && echo "Success"

関連する問題