Semaphores Assignment

Assignment

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
  }

after all die, use single call or loop based on ids saved above

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

Solution

For all your C homework help that you need, you won’t find a better place.

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>

/*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:

I hope that after reading through these examples you decide to contact us to offer you help with C assignment.