//hw 3- gcd.c //Dan Weinger //due: 2/24/05 #include #include #include #include #include #include #include #include void parent_handler(); void end_program(); void set_fl(int fd, int flags); int end_counter=0; int childpipes[100][2];//[1] is for writing, [0] is for reading int num_children; char **pairs; //copy ** pointer to this int gcd[100]; //will hold the results of gcd calculation main (int argc, char **argv) { int pid; int i, m, n; pid_t parent_pid=getpid(); //parent id, so children can send signals num_children=argc/2; pairs = argv; signal(SIGINT, parent_handler); signal(SIGUSR1, end_program); /* two pipes. one is for parent->child comm, the other for child->parent comm*/ for (i=1; i<=num_children;i++){ //spawns each child needed m=atoi(argv[2*i-1]); n=atoi(argv[2*i]); if (pipe(childpipes[(2*i)-2]) == -1) // child-->parent comm perror("couldn't make first pipe"); if (pipe(childpipes[(2*i)-1]) == -1) //parent-->child comm perror("couldn't make second pipe"); set_fl(childpipes[(2*i)-1][0], O_NONBLOCK); // set nonblocking pid=fork(); printf("children number %d, pid=%d\n", i, pid); if (pid==0) //if process is the child, break out of for loop break; } //for if (pid==0){ printf("child process %d\n", i); /* child */ sleep(1); while (n>0) //at which point m is the gcd { char buf[1024]; int length; int numread; printf("child process %d, m=%d, n=%d\n", i, m, n); sprintf(buf, "%d %d", m, n); //put numbers into a string so it can be passed in pipe length=strlen(buf); if (write(childpipes[(2*i)-1][1], buf, length) != length) perror("length not right"); kill( parent_pid, SIGINT); //signal for input ready bzero((void *)buf, 1024); while ((numread = read(childpipes[(2*i)-2][0], buf, length)) == -1) {} //non-blocking read. should read until there is something to read sscanf(buf, "%d %d", &m, &n); //puts new values into m and n bzero((void *)buf, 1024); if (n==0) break; } printf ("GCD of (%d, %d) is %d\n", atoi(argv[2*i-1]), atoi(argv[2*i]), m); kill( parent_pid, SIGUSR1); } //if else if (pid>0){ /* parent */ while(1) { //kill when all processes done if (end_counter == num_children) break; } }// else if else perror("couldn't fork"); exit(0); }//main void parent_handler() { int k, ret; int b,v, temp, length; signal(SIGINT, parent_handler); //reset signal char buf[1024]; for(k=1; k<=num_children; k++) //search through for something to do { if ((ret = read(childpipes[(2*k)-1][0], buf, 1024)) == 0){printf("fails\n");} //no new info in that pipe else //there is new info { if (ret == -1) { perror(NULL); } sscanf(buf, "%d %d", &b, &v); //sticks values into b and v printf("mod operation: b=%d, v=%d\n", b, v); temp = b % v; //zero out the buffer between reading from it and writing to it! bzero((void *)buf, 1024); sprintf(buf, "%d %d", v, temp); //puts new values into string so it can be passed back to child length=strlen(buf); write(childpipes[(2*k)-2][1], buf, length); break; }//else }//for }//void void end_program() /* prints results when all processes are finished. kills program */ { end_counter++; int l; if (end_counter == num_children) { exit(0); }//if }//void void set_fl(int fd, int flags) // flag=file status flags to turn on { int val; if ((val = fcntl(fd, F_GETFL, 0)) < 0) perror("fcntl F_GETFL error"); val |= flags; // turn on flags if (fcntl(fd, F_SETFL, val)<0) perror("fcntl F_SETFL error"); }//void