예제 #1
0
파일: parent.c 프로젝트: trusktr/csc60
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
}
예제 #2
0
파일: server.c 프로젝트: SnakeDoc/CSc60
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

}
예제 #3
0
파일: CR.c 프로젝트: SnakeDoc/CSc60
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;
}