//------------------------------------------------------------------- // gambler.cpp // // This program acts as a lottery-player client, using a shared // memory-segment to check the validity of a number-choice bet. // Our server program (named 'lottery.cpp') needs to be running // as a separate process. Here a player is prompted to type in // a 4-digit bet, which will be compared to the current winning // number, which is accessible through a shared memory-segment. // The program-pair illustrates the use of a UNIX semaphore-set // to appropriately coordinate access by the writer and reader. // // Our lottery-and-gambler program-pair was inspired by a time- // server example in "Understanding UNIX/Linux Programming" by // Bruce Molay (Prentice-Hall, 2003), pp. 506-514. // // programmer: ALLAN CRUSE // written on: 13 OCT 2004 //------------------------------------------------------------------- #include // for printf(), perror() #include // for exit() #include // for strncmp() #include // for shmget(), shmctl(), shmat(), etc #include // for semget(), semctl(), semop(), etc #include "myshmsem.h" // for MY_MEM_KEY, MY_SEM_KEY, MEM_SIZE int semset_id; // holds handle to the semaphore set int shmseg_id; // holds handle to the shared memory void *shm_buffer; // our pointer to the memory segment void wait_and_lock( int semset_id ) { struct sembuf actions[2]; // wait for 0 on n_writers actions[0].sem_num = 1; actions[0].sem_flg = SEM_UNDO; actions[0].sem_op = 0; // then increment n_readers actions[1].sem_num = 0; actions[1].sem_flg = SEM_UNDO; actions[1].sem_op = +1; if ( semop( semset_id, actions, 2 ) < 0 ) { perror( "semop" ); exit(1); } } void release_lock( int semset_id ) { struct sembuf actions[1]; // decrement n_readers actions[0].sem_num = 0; actions[0].sem_flg = SEM_UNDO; actions[0].sem_op = -1; if ( semop( semset_id, actions, 1 ) < 0 ) { perror( "semop" ); exit(1); } } int main( int argc, char **argv ) { // create a shared memory segment shmseg_id = shmget( MY_MEM_KEY, MEM_SIZE, 0666 ); if ( shmseg_id < 0 ) { perror( "shmget" ); exit(1); } // attach to it and obtain its address shm_buffer = shmat( shmseg_id, NULL, 0 ); printf( "shm_buffer=%p \n", shm_buffer ); // connect to semaphore-set with 2 semaphores semset_id = semget( MY_SEM_KEY, 2, 0 ); if ( semset_id < 0 ) { perror( "semget" ); exit(1); } // prompt the player for lottery number choices printf( "\nType in your 4-digit bet: " ); fflush( stdout ); // obtain the player's bet char mybet[ 5 ]; scanf( "%4s", mybet ); printf( "\nMy bet is %s \n", mybet ); // read from shared memory contents to determine win/lose int won; wait_and_lock( semset_id ); printf( "current winning number is %s\n", shm_buffer ); won = ( strncmp( (char*)shm_buffer, mybet, 4 ) == 0 ); release_lock( semset_id ); // detach this process from the shared memory segment shmdt( shm_buffer ); // report lottery result to the player if ( won ) printf( "You win!\n" ); else printf( "You lose\n" ); }