Named Semaphore just not working

764 views Asked by At

we had an exam today and we had a task to implement a "train-handler".

There are 7 trains represented by one process each. Each train arrives after a couple of seconds, checks if 1 of our 3 traintracks is available. If not, wait... If track is free, enter it and lock it. Stay for at the train station for a few seconds, leave and unlock it.

Me and a few friends are trying to make our program run but we just can't get it done. It seems to be the problem that our shared memory is not synchronized properly (semaphore). Using a mac, so I have to use named semaphores.

compiled with: "gcc -Wall -Werror -std=gnu99 -lpthread process_trains.c -o test"

CODE:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <errno.h>


sem_t *sem;
int *shm_ptr;



int *initShm (int size) {
    int shm_fd = 0;

    if((shm_fd = shm_open("/shm", O_CREAT | O_RDWR, 0777)) == -1) {
        perror("Error creating shared memory segment!");
    }

    if ((ftruncate(shm_fd, size)) == -1) {
        perror("Error sizing shared memory segment!");
    }

    return (int*) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
}


int trainAboutToArrive(int arrive, int stay, int Y){

    int Z=0;

    //Zug kommt in "arrive" Sekunden an
    sleep(arrive);

    while (shm_ptr[Z]!=0) {
        Z++;
        if(Z==3){
            Z=0;
        }
    }

    sem_wait(sem);
    shm_ptr[Z]=1;
    sem_post(sem);

    printf("Zug %d ist auf Gleis %d eingefahren\n", Y, 1+Z);

    //Zug hat einen Aufenthalt von "stay" Sekunden 
    sleep(stay);

    sem_wait(sem);
    shm_ptr[Z]=0;
    sem_post(sem);

    sem_close(sem);

    printf("Zug %d verlässt Gleis %d\n", Y, 1+Z);

    return EXIT_SUCCESS;
}

int main(int argc, char const *argv[]) {

    shm_unlink("shm");

    int i=0, tracks=3, trains=7, status;
    int arrival[]={0,0,3,2,5,4,2};
    int stay[]={2,3,7,2,1,4,3};

    off_t size = sizeof(int)*tracks;
    shm_ptr = initShm(size);

    if((sem = sem_open("/semap",O_CREAT,0644,1)) == SEM_FAILED) {
        perror("client sem_open");
    }

    for (i=0; i < tracks; i++) {
        shm_ptr[i]= 0;
    }

    pid_t pids[trains];

    for (i = 0; i < trains; i++) {
        pids[i] = fork();
        if(pids[i] == -1) {
            perror("Error creating train-process!!");
        } else if (pids[i] == 0) {
            trainAboutToArrive(arrival[i], stay[i], 1+i);
            exit(0);
        }else if (pids[i] > 0) {

        }
    }

    for(i=0; i < trains; i++){
        waitpid(pids[i], &status, 0);
    }
    shm_unlink("shm");

    return EXIT_SUCCESS;
}
1

There are 1 answers

0
MacHeath On

Link with -pthread!!!! man page of all used semaphore functions tells us >.<

Thanks for everyones help!!

And for everyone who's interested, this is my code now. I improved a lot of things I didn't have time for in the exam. This runs perfectly and in my "beginners-eyes" this is not improvable by using the given functions (semaphores, shared mem...). If it is, I'd be grateful for tips & tricks ;)

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <errno.h>

int *shm_ptr;

int *initShm (off_t size) {

    int shm_fd = 0;

    if((shm_fd = shm_open("/shm", O_CREAT | O_RDWR, 0777)) == -1) {
        perror("Error creating shared memory segment!");
    }

    if ((ftruncate(shm_fd, size)) == -1) {
        perror("Error sizing shared memory segment!");
    }

    return (int*) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
}

void initSem(sem_t **plats) {

    if((plats[0] = sem_open("/one",O_CREAT,0644,1)) == SEM_FAILED) {
        perror("client sem_open");
    }
    if((plats[1] = sem_open("/two",O_CREAT,0644,1)) == SEM_FAILED) {
        perror("client sem_open");
    }
    if((plats[2] = sem_open("/three",O_CREAT,0644,1)) == SEM_FAILED) {
        perror("client sem_open");
    }
}


int trainAboutToArrive(int arrive, int stay, int train, sem_t **plats){

    srand(getpid());
    int platform = rand()%3;

    sleep(arrive);

    while (3) {
        sem_wait(plats[platform]);
        if(shm_ptr[platform]==0){
            shm_ptr[platform]=1;
            break;
        }
        sem_post(plats[platform]);

        platform = rand() % 3;
    }

    printf("Train %d enters platform %d\n", train, 1+platform);

    sleep(stay);

    shm_ptr[platform]=0;

    printf("Train %d leaves platform %d\n", train, 1+platform);

    sem_post(plats[platform]);
    sem_close(plats[platform]);

    return EXIT_SUCCESS;

}

int main(int argc, char const *argv[]) {

    shm_unlink("/shm");
    sem_unlink("/one");
    sem_unlink("/two");
    sem_unlink("/three");

    int i=0, tracks=3, trains=7, status;
    int arrival[]={0,0,3,2,5,4,2};
    int stay[]={2,3,7,2,1,4,3};
    sem_t *plats[3];

    off_t size = sizeof(int)*tracks;
    shm_ptr = initShm(size);
    initSem(plats);

    for (i=0; i < tracks; i++) {
        shm_ptr[i]= 0;
    }

    pid_t pids[trains];

    for (i = 0; i < trains; i++) {
        pids[i] = fork();
        if(pids[i] == -1) {
            perror("Error creating train-process!!");
        } else if (pids[i] == 0) {
            trainAboutToArrive(arrival[i], stay[i], 1+i, plats);
            exit(0);
        }else if (pids[i] > 0) {

        }
    }

    for(i=0; i < trains; i++){
        waitpid(pids[i], &status, 0);
    }

    shm_unlink("/shm");
    sem_unlink("/one");
    sem_unlink("/two");
    sem_unlink("/three");

    return EXIT_SUCCESS;
}