void main() // no need of given args, use self pid as semaphore key { int c_row, c_col, r_row, r_col; int the_pipe[2]; // 1 pipe for both children sem_t *sem_video, *sem_c, *sem_r; char str[20]; // str for common usage char row_str[3], col_str[3], pipe_str[3], symbol_str[3]; // child's argv // prep video semaphore, start value 1, make it like a mutex sprintf( str, "%d", getpid() ); // build key str out of pid sem_video = sem_open( str, O_CREAT, 0600, 1 ); // prep Chaser semaphore, start value 0 sprintf( str, "%d", 'C'+getpid() ); // key str out of pid + 'C' sem_c = sem_open( str, O_CREAT, 0600, 1 ); // prep Runner semaphore, start value 0 sprintf( str, "%d", 'R'+getpid() ); // key str out of pid + 'R' sem_r = sem_open( str, O_CREAT, 0600, 1 ); if(sem_video == SEM_FAILED) // erred in sys call sem_open { perror("Error opening semaphore: "); return; } if( -1 == pipe(the_pipe) ) // 1 pipe for both children { perror("Error making pipe: "); return; } InitScr( sem_video ); // starting screen // prep argv for Chaser, starts at upper-left corner sprintf(row_str, "%d", 0); // starting row pos, packing info into str sprintf(col_str, "%d", 0); // starting col pos, packing info into str sprintf(pipe_str, "%d", the_pipe[1]); // pipe end for it to write back sprintf(symbol_str, "%c", 'C'); // Chaser's char symbol switch( fork() ) // launch Chaser child { case -1: perror("fork C: "); return; // error in fork case 0: execl( "./child", "./child", // start child proc with argv row_str, col_str, pipe_str, symbol_str, 0 ); } // prep argv for Runner, starts at lower-right corner sprintf(row_str, "%d", MAX_ROW); sprintf(col_str, "%d", MAX_COL); // sprintf(pipe_str, "%d", ...); // same pipe_str as above sprintf(symbol_str, "%c", 'R'); switch( fork() ) // launch Runner child { case -1: perror("fork R: "); return; case 0: execl( "./child", "./child", row_str, col_str, pipe_str, symbol_str, 0 ); } while(1) // let them play forever { sem_post( sem_c ); // allow Chaser 1 play move (loop once, see child.c) read( the_pipe[0], &c_row, sizeof(int) ); // read pos info row from Chaser read( the_pipe[0], &c_col, sizeof(int) ); // read pos info col from Chaser if(c_row == r_row && c_col == r_col) break; // collision occurred? sem_post( sem_r ); // allow Runner 1 play move (loop once, see child.c) read( the_pipe[0], &r_row, sizeof(int) ); // read pos info from Runner read( the_pipe[0], &r_col, sizeof(int) ); // read pos info from Runner if(c_row == r_row && c_col == r_col) break; // collision occurred? } sem_wait(sem_video); // since children are still running, hold till end Flash(); // flash screen, restore cursor sprintf(str, "%c[%d;%dH", 27, MAX_ROW+3, 1); // move cursor to bottom write(1, str, strlen(str)); printf("\n*** Chaser got Runner! *** \n"); // OK to use printf since printf("Chaser at row %d col %d\n", c_row, c_col); // we're all done with printf("Runner at row %d col %d\n", r_row, r_col); // moving around symbols // if not removed, same filename remains in /dev/shm/sem.<pid> sprintf( str, "%d", getpid() ); // build key str out of pid sem_unlink( str ); sprintf( str, "%d", 'C'+getpid() ); // build key str out of pid+'C' sem_unlink( str ); sprintf( str, "%d", 'R'+getpid() ); // build key str out of pid+'R' sem_unlink( str ); kill(0, SIGHUP); // shutdown all processes, include this }
int main( int argc, char* argv[] ) { char character; // current character char str[40]; // general purpose string pid_t pids[26]; // child alphabet pids info_t *info_c; // info_t for client info_t *info_c_m; // info_t for client monitor info_t* infos[26]; // info_t for all alphabets sem_t *sem_video; // video semaphore int finishing_place = 1; // starting finish place char termination_cond = '<'; // the termination condition sprintf( video_key_str, "%d", getpid() ); // create video semaphore sem_video = sem_open( video_key_str, O_CREAT, 0666, 1 ); if ( sem_video == SEM_FAILED ) { perror( "server semaphore" ); exit(1); } // request/allocate shared memory for client if( ( shmid_c = shmget( getpid()+32766, sizeof( info_t ), IPC_CREAT|0666 ) ) < 0 ) { perror( "server shmget" ); exit(1); } if( ( shmid_c_m = shmget( getpid()+32767, sizeof( info_t ), IPC_CREAT|0666 ) ) < 0 ) { perror( "server shmget" ); exit(1); } // attach to shared memory for client if( ( info_c = (info_t *)shmat( shmid_c, 0, 0 ) ) == (info_t *) -1 ) { perror( "server shmat" ); exit(1); } if( ( info_c_m = (info_t *)shmat( shmid_c_m, 0, 0 ) ) == (info_t *) -1 ) { perror( "server shmat" ); exit(1); } // set default alphabet character in client shared memory // we'll use this to notice a change, signaling the client // has made their choice and is ready to race info_c->alphabet = '*'; info_c->row = shmid_c_m; // give the client the monitoring shmid num info_c->col = -1; info_c->o_col = -1; info_c->start = 0; info_c->finishing_place = -1; info_c->points = -1; strcpy( info_c->sem_video_str, video_key_str ); // more defaults info_c_m->alphabet = '*'; info_c_m->row = -1; info_c_m->col = -1; info_c_m->o_col = -1; info_c_m->start = 0; info_c_m->finishing_place = -1; info_c_m->points = -1; strcpy( info_c_m->sem_video_str, video_key_str ); ClearScr( sem_video ); // display client shared memory id so user can // attach to the server printf( "From another shell, run client and pick winner.\n" ); printf( "Syntax: './client %d'\n", shmid_c ); // now setup the children alphabet process while waiting for client int i = 0; for ( character = 'A'; character <= 'Z'; character++ ) { if( ( shmids[i] = shmget( getpid()+32767+i, sizeof( info_t ), IPC_CREAT|0666 ) ) < 0 ) { perror( "server shmget alphabet" ); exit(1); } // attach to shared memory if ( ( infos[i] = (info_t *)shmat( shmids[i], 0, 0 ) ) == (info_t *) -1 ) { perror( "server shmat alphabet" ); exit(1); } // set defaults infos[i]->alphabet = character; infos[i]->row = ((int)character - 64); infos[i]->col = 1; // default starting column infos[i]->o_col = -1; // there is no old column yet infos[i]->start = 0; // don't start the race yet infos[i]->finishing_place = -1; // race has not started yet infos[i]->points = -1; // no points yet strcpy( infos[i]->sem_video_str, video_key_str ); i++; } for ( i = 0; i < 26; i++ ) { sprintf( str, "%d", shmids[i] ); pids[i] = fork(); if ( pids[i] == -1 ) { perror( "server fork alphabet" ); exit(1); } else if ( pids[i] == 0 ) { // in child process execl( "./alphabet", "alphabet", str, NULL ); } i++; usleep( USEC ); } // ensure we always cleanup atexit( exit_handler ); while( info_c->alphabet == '*' ) { usleep( USEC ); } printf( "\n >>>>>> Client picked '%c' <<<<<<\n", info_c->alphabet ); usleep( USEC * 6 ); ClearScr( sem_video ); InitScr( sem_video ); // On your marks! usleep( USEC * 3 ); // Get Set! usleep( USEC * 3 ); // Go! for ( i = 0; i < 26; i++ ) { infos[i]->start = 1; } info_c->start = 1; // loop and display children updates // also update client with new positions while ( 1 ) { int i; for ( i = 0; i < 26; i++ ) { PutChar( infos[i]->row, infos[i]->o_col, ' ', sem_video ); PutChar( infos[i]->row, infos[i]->col, infos[i]->alphabet, sem_video ); // update client monitor info_c_m->alphabet = infos[i]->alphabet; info_c_m->row = infos[i]->row; info_c_m->col = infos[i]->col; info_c_m->o_col = infos[i]->o_col; if ( infos[i]->col == MAX_COL ) { sem_wait( sem_video ); sprintf( str, "\033[%d;%dH", infos[i]->alphabet - 64, 62 ); write( OUT, str, strlen(str) ); sprintf( str, "<-- %d", finishing_place ); write( OUT, str, strlen(str) ); if ( finishing_place <= 5 ) { sprintf( str, "\033[%d;%dH", infos[i]->alphabet - 64, 68 ); write( OUT, str, strlen(str) ); sprintf( str, "%s", "***" ); write( OUT, str, strlen(str) ); } sem_post( sem_video ); infos[i]->finishing_place = finishing_place; infos[i]->points = 26 - finishing_place; // update client monitor info_c_m->finishing_place = infos[i]->finishing_place; info_c_m->points = infos[i]->points; finishing_place++; } } if ( finishing_place > 26 ) break; } // inform client race is over info_c_m->alphabet = termination_cond; // assign client their points info_c->points = infos[info_c->alphabet - 64]->points; FlashScr( sem_video ); CursorOn( sem_video ); printf( "Client points: %d\n", info_c->points ); if ( info_c->points < 21 ) { printf( "Better luck next time!\n" ); } else { printf( "Nice!\n" ); } return 0; // normal return }
int main( int argc, char* argv[] ) { int pipes[2]; char write_pipe_str[8]; int c_pos[2]; int r_pos[2]; sem_t *sem_video, *sem_c, *sem_r; char video_key_str[8]; char c_key_str[8]; char r_key_str[8]; pid_t video_key = getpid(); pid_t pids[2]; // create pipes for comms if ( -1 == pipe( pipes ) ) { perror( "pipe: "); exit(1); } sprintf( write_pipe_str, "%d", pipes[1] ); sprintf( video_key_str, "%d", video_key ); sprintf( c_key_str, "c_%d", video_key ); sprintf( r_key_str, "r_%d", video_key ); // create semaphores sem_video = sem_open( video_key_str, O_CREAT, 0600, 1 ); sem_c = sem_open( c_key_str, O_CREAT, 0600, 1 ); sem_r = sem_open( r_key_str, O_CREAT, 0600, 1 ); // check for semaphore creation errors if ( sem_video == SEM_FAILED ) { perror( "video sem: " ); exit(1); } if ( sem_c == SEM_FAILED ) { perror( "c sem: " ); exit(1); } if ( sem_r == SEM_FAILED ) { perror( "r sem: " ); exit(1); } // block semaphores so children don't start playing early sem_wait( sem_c ); sem_wait( sem_r ); // init screen sem_wait( sem_video ); InitScr(); sem_post( sem_video ); // create childres (C and R) int i; for ( i = 0; i < 2; i++ ) { pids[i] = fork(); if ( pids[i] == -1 ) { perror( "fork: " ); exit(1); } else if ( pids[i] == 0 ) { // in child process if ( i == 0 ) { // chaser execl( "./child", "child", "C", write_pipe_str, c_key_str, video_key_str, NULL ); } else if ( i == 1 ) { // runner execl( "./child", "child", "R", write_pipe_str, r_key_str, video_key_str, NULL ); } } } // round robin children until C catches R while( 1 ) { usleep( USEC ); sem_post( sem_r ); read( pipes[0], &r_pos[0], sizeof(int) ); read( pipes[0], &r_pos[1], sizeof(int) ); usleep( USEC ); sem_post( sem_c ); read( pipes[0], &c_pos[0], sizeof(int) ); read( pipes[0], &c_pos[1], sizeof(int) ); if ( c_pos[0] == r_pos[0] && c_pos[1] == r_pos[1] ) { // Chaser caught Runner for ( i = 0; i < 2; i++ ) { kill( pids[i], SIGTERM ); } FlashScr(); printf( "*** Chaser got Runner! ***\n" ); printf( "row # %d == %d\n", c_pos[0], r_pos[0] ); printf( "col # %d == %d\n", c_pos[1], r_pos[1] ); break; } } // cleanup close( pipes[0] ); close( pipes[1] ); sem_unlink( video_key_str ); sem_unlink( c_key_str ); sem_unlink( r_key_str ); return 0; }