eventfd 和线程的关键部分

标签 c unix operating-system pthreads semaphore

我有一点问题似乎无法解决。我正在尝试实现一个程序(针对 uni 类),该程序将有 n 列火车和 m 列火车。但是,由于我的车站数量可能少于试图访问它们的火车,我想在关键部分(这将是我的火车站)添加一个类似信号量的机制,但我们必须使用而不是使用信号量我们操作系统类中的 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

非常感谢您的宝贵时间和帮助!

最佳答案

好像是指针的小错误?

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));

关于eventfd 和线程的关键部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37674476/

相关文章:

linux - 如何在linux命令行中读取文件?

java - 获取当前年份值到字符串

c# - 我如何以编程方式使用 C# 代码中的 aero snap 功能

c - sizeof(2147483648) 是 8 个字节,而 sizeof(2147483647+1) 是 4 个字节

代码在 AIX 5.3 上编译,但在 AIX 7.1 上编译,这与 struct shl_descriptor 有关,这是在哪里定义的?

c - Valgrind 内存泄漏报告中的时间戳不正确

linux - 为什么 vim 默认连接到 X?

operating-system - 分页:基本、分层、散列和倒置

c - 我正在从标准输入文件读取整数,并且必须在用户停止输入整数时停止。如何做到这一点?

c - 使用 Ptrace 找出参数对系统调用到底意味着什么