//----------------------------------------------------------------------------- // // File Name: semtest.c v1.1 // // by: Jason Breti (http://breti.org) // // This code is entirely open source. You may use it in any way you see fit. // // The purpose of this file is to show you how to use the System V semaphore // as a mutex semaphore. You can use the interface from several different // processes at the same time to test how the semaphore locks and unlocks. // //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Include Files //----------------------------------------------------------------------------- #include #include #include #include #include #include #include //----------------------------------------------------------------------------- // Type Declarations //----------------------------------------------------------------------------- #define SEM_DIRECTORY "/tmp/mutexSemaphore" #define SEM_SHAREDMEM_SEMAPHORE_FILE "semfile" // Semaphore ftok() ID parameter used between the interface and agent. #define SEM_KEY_ID 0x01 // Length of the string buffer for creating a semaphore filename #define BUFFER_LENGTH 256 //----------------------------------------------------------------------------- // Global Constant //----------------------------------------------------------------------------- int madeSemaphore = 0; //----------------------------------------------------------------------------- // Static Variable //----------------------------------------------------------------------------- // A file for use by the semaphore. int theMutexSemFile; // A token for use by the semaphore. key_t theMutexSemToken; // A semaphore for managing access to the shared memory int theMutexSem; // Lock semaphore parameters ready for use. struct sembuf theMutexLock; // Unlock semaphore parameters ready for use. struct sembuf theMutexUnlock; //----------------------------------------------------------------------------- void resetSemaphoreValues(void) { printf("resetSemaphoreValues()\n"); theMutexLock.sem_num = 0; theMutexLock.sem_op = -1; theMutexLock.sem_flg = 0; theMutexUnlock.sem_num = 0; theMutexUnlock.sem_op = 1; theMutexUnlock.sem_flg = 0; } //----------------------------------------------------------------------------- void outputSemaphoreValues(void) { printf("theMutexLock: sem_num: %02d sem_op: %02d sem_flg: %02d\n", theMutexLock.sem_num, theMutexLock.sem_op, theMutexLock.sem_flg); printf("theMutexUnlock: sem_num: %02d sem_op: %02d sem_flg: %02d\n", theMutexUnlock.sem_num, theMutexUnlock.sem_op, theMutexUnlock.sem_flg); } //----------------------------------------------------------------------------- void outputSemaphoreCount(void) { int semValue; semValue = semctl(theMutexSem, 0, GETVAL); printf("semval: %d\n",semValue); } //----------------------------------------------------------------------------- /**-------------------------------------------------------------------------- * * Name: main * * Description: See the header at the top of the file * * @param argc - The number of incoming arguments from the command line. * This parameter is ignored. * * @param argv - An array of strings of the arguments from the command line. * This parameter is ignored. * * @return - 0 (never changes) * *--------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int status = 0; // Configure the semaphore commands for locking and unlocking resetSemaphoreValues(); char input = '\0'; do { if (input != '\n') { printf("---------------------------------------------\n"); printf("Input command:\n"); printf(" x - exit\n"); if (!madeSemaphore) { printf(" m - make semaphore\n"); } else { printf(" s - status\n"); printf(" r - reset semaphore (to 1)\n"); printf(" l - lock semaphore (%d)\n", theMutexLock.sem_op); printf(" u - unlock semaphore (%d)\n", theMutexUnlock.sem_op); } printf("---------------------------------------------\n"); } input = getchar(); if (isalpha(input)) { printf("%c\n",input); } switch (input) { case 'm': // make semaphore { if (!madeSemaphore) { printf("make semaphore - begin\n"); //--------------------------------------------------------------------------------- // Create a directory for holding the semaphore //--------------------------------------------------------------------------------- char buffer[BUFFER_LENGTH]; sprintf(buffer, SEM_DIRECTORY); //Directory to create errno = 0; int dirCreateRc = mkdir(buffer, S_IRWXU | S_IRWXG | S_IRWXO); //Permission: drwxr-x--- if (dirCreateRc == -1) { // errno(17): indicates "directory already exist", this is not considered // an error which is reported if (errno != 17 ) { //Error attempting to create the directory, exist printf("Directory creation %s returned ERROR: errno %d (%m)\n", buffer, errno); } } //(end) if (dirCreateRc == -1) //--------------------------------------------------------------------------------- // Create a file for holding the semaphore //--------------------------------------------------------------------------------- sprintf(buffer, "%s/%s", SEM_DIRECTORY, SEM_SHAREDMEM_SEMAPHORE_FILE); if (( theMutexSemFile = open(buffer, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO)) == -1) { printf("theMutex file open problem: %m\n"); } printf("theMutexSemFile: %d\n", theMutexSemFile); // Open the file token for the semaphore theMutexSemToken = ftok(buffer, SEM_KEY_ID); if( theMutexSemToken == (key_t)(-1) ) { printf( "ftok failed: %s (%d)\n", strerror(errno), errno ); } printf("theMutexSemToken: %x\n", theMutexSemToken); // Configure the semaphore theMutexSem = semget( theMutexSemToken, 1, IPC_CREAT | 0666); if( -1 == theMutexSem ) { printf("Semget failed - %s (%d)\n", strerror(errno), errno); } printf("theMutexSem: %d\n", theMutexSem); // Configure the semaphore commands for locking and unlocking resetSemaphoreValues(); // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); madeSemaphore = 1; printf("make semaphore - end\n\n"); } break; } case 's': // status { if (madeSemaphore) { printf("status - begin\n"); printf("theMutexSemFile: %d\n", theMutexSemFile); printf("theMutexSemToken: %x\n", theMutexSemToken); printf("theMutexSem: %d\n", theMutexSem); // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); printf("status - end\n\n"); } break; } case 'r': // Reset semaphore { if (madeSemaphore) { printf("reset semaphore - begin\n"); int initialSemaphoreValue; initialSemaphoreValue = 1; if( -1 == semctl( theMutexSem, 0, SETVAL, initialSemaphoreValue) ) { printf("semctl failed - %s (%d)\n", strerror(errno), errno); } // print out the current count of the semaphore outputSemaphoreCount(); printf("reset semaphore - end\n\n"); } break; } case 'l': // lock semaphore { if (madeSemaphore) { printf("lock semaphore - begin\n"); // Configure the semaphore commands for locking and unlocking resetSemaphoreValues(); // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); // lock the semaphore if( 0 == semop( theMutexSem, &theMutexLock, 1 ) ) { printf("theMutex lock successful: %m (%d)\n",errno); } else { printf("theMutex lock fails: %m (%d)\n",errno); } // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); printf("lock semaphore - end\n\n"); } break; } case 'u': // unlock semaphore { if (madeSemaphore) { printf("unlock semaphore - begin\n"); // Configure the semaphore commands for locking and unlocking resetSemaphoreValues(); // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); // unlock the semaphore if( 0 == semop( theMutexSem, &theMutexUnlock, 1 ) ) { printf("theMutex unlock successful: %m (%d)\n",errno); } else { printf("theMutex unlock fails: %m (%d)\n",errno); } // print out the current count of the semaphore outputSemaphoreCount(); outputSemaphoreValues(); printf("unlock semaphore - end\n\n"); } break; } } } while (input != 'x'); return status; }//main //-----------------------------------------------------------------------------