打印使用信号的奇数号码

问题描述:

我需要打印自然数。 1,2,... n,以便父进程打印所有奇数,并且子进程打印所有偶数,并且所有这些都需要使用POSIX信号完成。我将如何去完成这件事?打印使用信号的奇数号码

输出应该是:

家长:1
儿童:2
家长:3
...

我觉得这个家庭作业是给你让你尝试了很多的解决方案,并由您自己得出结论,信号不是一个好的同步技术

这是一个宝贵的教训,记住它并且从现在开始使用信号量! :)

它可能会更有利于你提供你所拥有的,到目前为止,并解释为预期的不工作,但这里是我想出了:

#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"