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