2008-08-29 6 views
1

Ich muss natürliche nos drucken. 1,2, ... n, so dass der Elternprozess alle ungeraden Zahlen ausgibt und der Kindprozess alle geraden Zahlen druckt, und all dies muss mit POSIX-Signalen geschehen. Wie würde ich das erreichen? seinDrucken Odd-Even-Nummern mit Signalen

sollte die Ausgabe:

Parent: 1
Kind: 2
Parent: 3
...

Antwort

3

ich diese Hausaufgabe denken wurde Ihnen gegeben zu machen versuchen Sie eine Menge Lösung und schließen Sie selbst, dass Signale sind keine gute Synchronisationstechnik.

Dies ist eine unschätzbare Lektion, erinnere dich gut daran und benutze ab jetzt Semaphore! :)

4

würde es wahrscheinlich von Vorteil sein, für Sie zur Verfügung stellen, was Sie bisher haben und erklären, was nicht funktioniert wie erwartet, aber hier ist, was ich kam mit:

#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; 
} 

Dies diese grundlegenden Tests bestanden :

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