#include #include #include #include #include #include #include #include #include #define SLEEPDELAY 1 #define NCHILD 4 pid_t children[NCHILD]; void ERROR(int ret, char * str) { int i; if (ret < 0) { perror(str); for (i=0; i 0) { kill (children[i], SIGKILL); } } exit (1); } } #define DOREAD (SIGRTMIN) #define READDONE (SIGRTMIN+1) #define BUSY (SIGRTMIN+2) #define DONE (SIGRTMIN+3) #define THEEND (SIGRTMIN+4) pid_t parent = 0; volatile sig_atomic_t doread = 0; void doread_handler (int sig, siginfo_t * info, void * arg) { if (info && info->si_code == SI_USER && info->si_pid == parent) doread = 1; } void busy_handler (int sig, siginfo_t * info, void * arg) { if (getpid () == parent) return; if (info && info->si_code == SI_USER && info->si_pid == parent) kill (getppid (), BUSY); } volatile sig_atomic_t terminate = 0; void child_termhandler (int sig, siginfo_t * info, void * a) { if (getpid() == parent) return; terminate = 1; } void parent_termhandler (int sig, siginfo_t * info, void * a) { int i; if (getpid () == parent && info && info->si_code == SI_USER) { for (i=0; isi_pid == children[i]) terminate = 1; } } } volatile sig_atomic_t childstatus = 0; void parent_handler (int sig, siginfo_t * info, void * a) { int i; if (getpid () == parent && info && info->si_code == SI_USER) { for (i=0; isi_pid == children[i]) childstatus = sig; } } } volatile sig_atomic_t factoring_done = 0; void done_handler (int sig, siginfo_t * info, void * a) { int i; if (getpid () == parent && info && info->si_code == SI_USER) { for (i=0; isi_pid == children[i]) factoring_done = 1; } } } int main () { int fd, i; struct sigaction act; fd = open ("INPUT", O_RDONLY); ERROR(fd,"open"); parent = getpid(); act.sa_sigaction = busy_handler; act.sa_flags = SA_SIGINFO; sigemptyset (&act.sa_mask); ERROR(sigaction (DOREAD, &act, NULL), "sigaction"); act.sa_sigaction = parent_handler; ERROR(sigaction (READDONE, &act, NULL), "sigaction"); ERROR(sigaction (BUSY, &act, NULL), "sigaction"); act.sa_sigaction = parent_termhandler; ERROR(sigaction (THEEND, &act, NULL), "sigaction"); act.sa_sigaction = child_termhandler; ERROR(sigaction (SIGTERM, &act, NULL), "sigaction"); act.sa_sigaction = done_handler; ERROR(sigaction (DONE, &act, NULL), "sigaction"); for (i=0; i= 0 || errno != ECHILD); exit (0); } /* Child */ act.sa_sigaction = doread_handler; ERROR (sigaction (DOREAD, &act, 0), "sigaction"); while (!terminate) { long long request; long long factor; int ret, factored; if (!doread) { sleep (SLEEPDELAY); continue; } doread = 0; ret = read (fd, &request, sizeof (request)); if (ret != sizeof (request)) { /* Probably End of file */ kill (getppid (), THEEND); kill (getppid (), BUSY); continue; } /* Ok, we've read a request. Adjust signal handler. */ act.sa_sigaction = busy_handler; ERROR(sigaction (DOREAD, &act, NULL), "sigaction"); /* Tell parent we're done reading. */ kill (getppid(), READDONE); /* Factor */ factored = 0; long long limit = request; if (limit < 0) limit = - request; if (request % 2LL == 0LL) { printf ("%lld = 2 * %lld\n", request, request/2); fflush (stdout); factored = 1; } for (factor=2; !factored && factor*factor <= limit; ++factor) { if (request % factor) continue; printf ("%lld = %lld * %lld\n", request, factor, request/factor); fflush (stdout); factored = 1; break; } if (!factored) { printf ("%lld is prime\n", request); fflush (stdout); } /* Done set doread handler */ act.sa_sigaction = doread_handler; ERROR(sigaction (DOREAD, &act, NULL), "sigaction"); /* Wake up parent if neccessary. */ kill (getppid (), DONE); } return 0; }