#include #include #include void forkprocess(int, char**, int); void setNonBlocking(int); int numToSpawn; int numChildren = 0; int count = -1; int pipesin[1000]; int pipesout[1000]; void int_handler(int sig) { signal(SIGUSR1, int_handler); /* parent */ char outbuf[1024]; int a, b, c, i, n, length; for (i = 0; i < count; i++) { n = read(pipesin[i], outbuf, 1024); if (n != 0) break; } sscanf(outbuf, "%d %d", &a, &b); c = a - b; while (c >= b) c = c - b; sprintf(outbuf, "%d", c); length = strlen(outbuf); if (write(pipesout[count], outbuf, length) != length) perror("write to pipe"); } int parent_pid; main(int argc, char **argv) { // check the command line input to make sure it's pairs of numbers if (argc % 2 == 0 || argc == 1) { printf("input must be a set of pairs of numbers"); exit(0); } int i = 1; int j; while(i < argc) { for(j = 0; j < strlen(argv[i]); j++) { if (!isdigit(argv[i][j])) { printf("input must be a set of pairs of numbers"); exit(0); } } i++; } signal(SIGUSR1, int_handler); numToSpawn = (argc - 1) / 2; parent_pid = getpid(); forkprocess(argc, argv, 1); } void forkprocess(int argc, char **argv, int position) { int pipev[2]; int pipev2[2]; int length; int i; char buf[1024]; char buf2[1024]; for(i = 0; i < numToSpawn; i++) { // open one pipe to read from child if (pipe(pipev) == -1) perror("open pipe"); //open second pipe to write to child if (pipe(pipev2) == -1) perror("open pipe"); count++; pipesin[count] = pipev[0]; pipesout[count] = pipev2[1]; setNonBlocking(pipesin[count]); numChildren++; int pid = fork(); /* error */ if (pid < 0) perror("fork"); /* child */ else if (pid == 0) { close(pipev[0]); close(pipev2[1]); int last, next, m, n; sscanf(argv[position + 1], "%d", &last); sscanf(argv[position], "%d", &next); m = next; n = last; sprintf(buf, "%s %s", argv[position], argv[position + 1]); length = strlen(buf); if (write(pipev[1], buf, length) != length) perror("write to pipe"); while(1) { next = last; read(pipev2[0], buf2, 1024); sscanf(buf2, "%d", &last); if (last == 0) { printf("GCD(%d, %d) = %d ", m, n, next); exit(0); // for child, this does nothing! // numChildren--; } sprintf(buf, "%d %d", next, last); // may need to clean buffer if (write(pipev[1], buf, length) != length) perror("write to pipe"); //signal(SIGUSR1, int_handler); kill(parent_pid, SIGUSR1); } } position = position + 2; } while (1){ wait(); if (--numChildren == 0) exit(0); } } void setNonBlocking(int fd) { int val; if ((val = fcntl(fd, F_GETFL, 0)) < 0) perror("fcntl F_GETFL error"); val |= O_NONBLOCK; // turn on flags if (fcntl(fd, F_SETFL, val)<0) perror("fcntl F_SETFL error"); }