Semaphore Assignment
Sets up deadlock conditions for practice detecting and recovering.Submit your .c source files and make file if needed
Two semaphores needed screen, keyboard
Use NAMED semaphores, do not use unnamed or memory based. Must use sem_open() NOT sem_init().
“Named semaphores”
and
“Unnamed semaphores (memory-based semaphores)”
The text below is called an algorithm, English description or design for code. If you make this into comments you can put your code under each line which is how designs work.
mother process called ‘main’
sem_open both semaphores fork 9 processes Each process passed index of loop so 1,2,3, or 4 Below is real C to show just how easy this is, please do not overthink for(i=1; i <= 9; i++) { if( fork() == 0) { // is child copy process( i ); } // you can else to save process ids if you want here }
sem_unlink both End Mother process each process Process (index) sem_open both semaphores if necessary count = 0 loop count += getSemaphores(index) prompt "enter < 80 characters or q to quit: " read keboard echo sem_post or give back both semaphores until quit end inner loop in C do ... while not q count += getSemaphores(index) prompt "This process had " + count + " deadlocks " sem_post or give back both semaphores sem_close exit function to get semaphores (index) returns count of how many times recovered from deadlock odd index gets screen first even index gets keyboard first count = 0 loop sem_wait for first sem_timedwait with timer for second if timeout give back first, (sem_post) wait random time increment count else have both true until have both return count end get semaphores function
main.c
#include#include #include #include #include #include #include #include #include #include #include /*Prototypes*/ void process(int idx); int getSemaphores(int idx); /*Macros*/ #define MAXBUFFER 80 #define KEYBSEM "/keybrd" #define SCRNSEM "/screen" #define MAX_PROCESS 9 sem_t * semScrn; sem_t * semKey; /*Creates named semaphores, then forks 9 processes that call process, and finally waits for the children processes to die before unlinking the semaphores and exiting.*/ int main(int argc, char const *argv[]) { pid_t pid[MAX_PROCESS]; int i = 0; /*Open the semaphore used by processes*/ sem_unlink(SCRNSEM); //unlink if already there sem_unlink(KEYBSEM); if ((semScrn = sem_open(SCRNSEM, O_CREAT, S_IRGRP | S_IWGRP, 1)) == SEM_FAILED) { perror("sem_open1"); exit(0); } if ((semKey = sem_open(KEYBSEM, O_CREAT, S_IRGRP | S_IWGRP, 1)) == SEM_FAILED) { perror("sem_open2"); exit(0); } /*fork children processes with indices*/ for (i = 0; i < MAX_PROCESS; i++) { pid[i] = fork(); if (pid[i] == 0) { //child process, send off process(i + 1); } } //parent, wait for children if (pid != 0) { //fprintf(stderr, "I am the parent with pid: %d\n", getpid()); for (i = 0; i < MAX_PROCESS; i++) { if (waitpid(pid[i], NULL, 0) == -1) { perror("waitpid"); } } //once all children die, unlink semaphores sem_unlink(SCRNSEM); sem_unlink(KEYBSEM); } return 0; } /*Uses getSemaphores() to lock the required semaphores, and then echos input until a 'q' is read. The function exits at the end (kills child once it has echoed enough times rather than returning to the fork loop). Before it exits, it posts and closes used semaphores.*/ void process(int idx) { srand(time(NULL)); int count = 0; char buffer[MAXBUFFER]; if ((semScrn = sem_open(SCRNSEM, O_CREAT, S_IRGRP | S_IWGRP, 1)) == SEM_FAILED) { perror("sem_open1"); exit(0); } if ((semKey = sem_open(KEYBSEM, O_CREAT, S_IRGRP | S_IWGRP, 1)) == SEM_FAILED) { perror("sem_open2"); exit(0); } do { count += getSemaphores(idx); fprintf(stdout, ">> Process %d. Enter < %d characters or q to quit\n", getpid(), MAXBUFFER); fprintf(stdout, ">> "); if (!fgets(buffer, MAXBUFFER, stdin)) { if (sem_post(semScrn) == -1 || sem_post(semKey) == -1) { perror("sme_post"); } break; } fprintf(stdout, ">> Echo: %s", buffer); if (sem_post(semScrn) == -1 || sem_post(semKey) == -1) { perror("sme_post"); } } while (strncmp(buffer, "q", 1) != 0); count += getSemaphores(idx); fprintf(stdout, ">> This is process %d: Had %d deadlocks\n", getpid(), count); if (sem_post(semScrn) == -1 || sem_post(semKey) == -1) { perror("sme_post"); } if (sem_close(semScrn) == -1 || sem_close(semKey) == -1) { perror("sme_close"); } exit(0); } /*locks the two semaphores (screen and keybrd) with deadlock checking and resolution, and returns the number of deadlock incountered.*/ int getSemaphores(int idx) { int deadlocks = 0; int gotBoth = 0; int r = 0; struct timespec ts; while (gotBoth == 0) { if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { perror("clock_gettime"); } ts.tv_sec += 1; if (idx % 2 == 0) { //even index gets keyboard first sem_wait(semKey); sleep(1); r = sem_timedwait(semScrn, &ts); } else { //odd index gets screen first sem_wait(semScrn); sleep(1); r = sem_timedwait(semKey, &ts); } if (r == -1) { //fprintf(stderr, "got a deadlock!\n"); if (errno == ETIMEDOUT) { //deadlock, give back and wait rand time if (idx % 2 == 0) { if (sem_post(semKey) == -1) { perror("sem_post"); } } else { if (sem_post(semScrn) == -1) { perror("sem_post"); } } } else perror("sem_timedwait"); deadlocks++; sleep(rand() % 3); } else gotBoth = 1; } return deadlocks; }
Index:
- main.c