具有eventfd和线程的关键部分

时间:2016-06-07 08:39:56

标签: c unix operating-system pthreads semaphore

我有点问题,似乎无法解决这个问题。我正在尝试实施一个程序(对于一个单一类),它将有n个列车和m个列车。但是,由于我的站点数量可能少于试图访问它们的列车,​​我想在关键部分(这将是我的火车站)添加信号量机制,但不使用信号量,我们必须使用我们的os类中的eventfd。 现在我的代码(到目前为止)的问题似乎是我的列车线程中没有一个实际进入车站。

我的代码是:

    //Task 1 - sync via eventfd 
//train example : 6 trains and just 3 alleys in a critical section -> train station
// threads = trains will stay = sleep in trainstation and print their current state

#include <sys/eventfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h> //needed for our in-kernel counter
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>

//eventfd: read with EFD_SEMAPHORE will decrease counter by 1 and return 1
// int eventfd(unsigned int initval, int flags);
// without just the previous value and resets to zero
// if eventfd counter is at zero when trying to read, it will block until it turns nonzero again (only if fd is not nonblocking!)
// ssize_t read(int fd, void *buf, size_t count); returns no of bytes if it succeeds
// write adds a number to our 64 bit in-kernel counter
// ssize_t write(int fd, const void *buf, size_t count);
// fd is readable to select, poll, epoll if the counter is non zero
// select - monitors multiple fds until one or more turn "ready"
// poll - waits for an event on a fd 
// epoll - similar to poll - monitors multiple fds to see if i/o is possible (great for large numbers of fds)
// close - required to release the fd - if all fds get closed = resources will be freed by the kernel
// return value = fd used to refer to the eventfd object; unsuccessful = -1

#define fail(msg) {printf(msg); return EXIT_FAILURE;}

struct stationStruct{
    int stations[3];
    uint64_t sem[3];
};

void threadfunction(void* station){
    int n = 3;
    struct stationStruct *st = station;
    int stillWaiting = 1;
    //reads eventfd to check wether train can enter or not
    while(stillWaiting != 0){
        for(int i = 0; i < n && stillWaiting != 0; i++){
            if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){
                stillWaiting = 0;
                printf("\n\ntrain no %ld has arrived at train station no %d \n", (long) pthread_self(), i);
                sleep(1);
                printf("train no %ld is ready for departure\n", (long) pthread_self());
                sleep(2);
                printf("train no %ld has left the train station %d\n", (long) pthread_self(), i);
                //writes in order to release the locked eventfd
                write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));
                break;
                }
                //else{
                //sleep(3);
                //printf("train %ld has failed to enter station %d\n", (long) pthread_self(), i);
            //}
        }
    }
    pthread_exit((void*)pthread_self);
}

int main(int argc, char const *argv[])
{
    int n = 3;
    int m = 4;
    struct stationStruct station;

    //eventfd creation
    for(int i = 0; i < n; i ++){
        if((station.stations[i] = eventfd(1, EFD_SEMAPHORE)) > 0){
            printf("Station %d is open\n", i);
        }
        else{
            fail("could not initialize eventfd for station A\n");
        }
    }

    pthread_t threads[m];
    int returnedValues[m];

    printf("Train Stations 0 - %d are open \n", n);
    for(int i = 0; i < m; i++){
        sleep(1);
        if(pthread_create(&threads[i], NULL, (void*) &threadfunction, (void*)&station) != 0){
            fail("trains did not arrive\n");
        }
    }

    for(int i = 0; i < m; i++){
        pthread_join(threads[i], (void*) &returnedValues[i]);
        printf("Traind %ld left for good\n", (long) threads[i]);
    }

    printf("Train stations are closing now...\n");
    for(int i = 0; i < n; i++){
        printf("sation %d has been closed\n", i);
        close(station.stations[i]);
    }

    printf("Main station has been closed\n");

    return EXIT_SUCCESS;
}

#define _XOPEN_SOURCE

非常感谢你的时间和帮助!

1 个答案:

答案 0 :(得分:2)

似乎是一个小指针错误?

if(read(st->stations[i], (void*) st->sem[i], sizeof(uint64_t)) > 0){

...

write(st->stations[i], (void*) st->sem[i], sizeof(uint64_t));

应该是

if(read(st->stations[i], &st->sem[i], sizeof(uint64_t)) > 0){

...

write(st->stations[i], &st->sem[i], sizeof(uint64_t));