/*************************************************** * mgcd.c * * MULTI-PROCESS GCD COMPUTATION * * When you call "mgcd" with n pairs of integers, * the parent process will spawn n child processes. Each child process * will compute the gcd of a pair of integers. * * The Euclidean algorithm is used: the GCD * of m, n (where m>n>=0) is computed via a sequence * * m_0 > m_1 > m_2 >...> m_k > m_{k+1} = 0 * * where m_{i+1} = m_{i-1} mod m_i for all i. * We return m_k as the GCD of m,n. * * However, each child process must call the parent process * to compute the mod operation. We set up two arrays of pipes * pipe2parent[20][2] and pipe2child[20][2] * between each child and the parent. The i-th child will write * a pair of numbers (a,b) into the pipe2parent[i][1], * and the parent will return the result (a mod b) into pipe2child[i][0]. * To find such pairs (a,b), the parent will read * each pipe2parent[j] (j=0,1,2,...) in a non-blocking way. * The i-th child will keep reading pipe2child[i][0] until it receives * the answer from its parent. When the child has found * the GCD, it prints this "GCD(m,n)=d" for suitable m,n,d, and exits. * * The parent also keeps track of the number of children that * has found its GCD (this corresponds to the number of times it * returns a 0 back to a child). The parent exits when all the * children has found its GCD. * * E.g., * > gcd_par 100 154 3 2 25 15 * * child 1: gcd(3,2)=1 * child 0: gcd(100,154)=4 * child 2: gcd(25,15)=5 * parent exits! * * SYSTEM HACK: We may need to call "sleep(1)" to slow down * down the processes, or else program hangs * when there are more than 2 processes * * * Chee Yap (Oct 2006) * Solution to Hw2, Operating Systems Class ****************************************************/ #include #include #include #include #include #include #include #include //////////////////////////////////////////////////// // Global variables //////////////////////////////////////////////////// // N is maximum number of children #define N 20 int pipe2parent[N][2]; //array of pipes int pipe2child[N][2]; //array of pipes char buf[1024]; //buffer //////////////////////////////////////////////////// // Routine to set status flag for files //////////////////////////////////////////////////// void set_fl(int fd, int flags) // flag contains bits 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"); }// //////////////////////////////////////////////////// // Swap values //////////////////////////////////////////////////// void swap(int *a, int *b) { int tmp; tmp=*a; *a=*b; *b=tmp; }// //////////////////////////////////////////////////// // Clear buffer //////////////////////////////////////////////////// void clearbuf(char *buff){ int i; for (i=0; i<1024; i++) buff[i]='\0'; }// //////////////////////////////////////////////////// // main //////////////////////////////////////////////////// int main(int argc, char ** argv) { int NumPairs = (argc-1)/2; printf("Number of Pairs = %d\n", NumPairs); if (NumPairs> N) perror("too many pairs"); int i; int m, n, mm, nn; int len; int child_pid, parent_pid; int countdown = NumPairs; //////////////////////////////////////////////////// //fork children processes //////////////////////////////////////////////////// for (i=0; i< NumPairs; i++){ // get args m = atoi(argv[2*i + 1]); n = atoi(argv[2*i + 2]); printf("%d-th Pair %d, %d\n", i,m,n); if (m0) { sleep(1); // hack to overcome some system bug // write m and n clearbuf(buf); sprintf(buf,"%d %d ",mm,nn); len = strlen(buf); if (len != write(pipe2parent[i][1],buf,len)) perror("write to parent"); // read p clearbuf(buf); //printf("reading pipe2child\n"); while (read(pipe2child[i][0], buf, 1024)<= 0); //printf("done reading pipe2child\n"); mm=nn; sscanf(buf,"%d", &nn); printf("got it!\n"); } printf("gcd(%d, %d)= %d\n", m,n,mm); exit(0); break; default: // parent close(pipe2parent[i][1]); close(pipe2child[i][0]); }//switch }//for i //////////////////////////////////////////////////// //main parent loop //////////////////////////////////////////////////// printf("parent loop\n"); while (countdown>0) { // countdown=number of live children for (i=0; i< NumPairs; i++){ clearbuf(buf); //printf("reading pipe2parent\n"); if (read(pipe2parent[i][0], buf, 1024)>0) { //printf("done reading pipe2parent\n"); sscanf(buf,"%d %d", &m, &n); clearbuf(buf); sprintf(buf,"%d", m%n); if (m%n == 0) countdown--; len = strlen(buf); if (len != write(pipe2child[i][1],buf,len)) perror("write to child"); } } } printf("Parent die\n"); }//main //////////////////////////////////////////////////// // END ////////////////////////////////////////////////////