使用CreateEvent和WaitForMultipleObjects到Linux

时间:2016-02-08 17:18:53

标签: c++ linux multithreading winapi events

我需要将使用Windows API函数SetEventCreateEventWaitForMultipleObjects的多进程应用程序移植到Linux。我找到了很多关于这个问题的主题,但没有一个为我的问题提供合理的解决方案。

我有一个应用程序,它分为三个进程,并通过这些事件管理一个进程的线程工作池。

我有多个解决方案来解决这个问题。一种是在Linux上使用mkfifo在Linux上创建FIFO特殊文件,并使用select语句来唤醒线程。问题是此解决方案的运行方式与WaitForMultipleObjects不同。例如,如果workerpool的10个线程将等待事件并且我调用SetEvent五次,那么正好五个workerthreads将被唤醒并完成工作,当在Linux中使用FIFO变体时,它会唤醒每个线程,我在select语句中等待数据放入fifo。描述这种情况的最佳方式是Windows API类似于一个计数为1的全局信号量。

我还考虑过使用pthreadscondition variables重新创建并通过共享内存(shm_openmmap)共享变量,但我遇到了同样的问题这里!

在Linux上重新创建此行为的合理方法是什么?我在一个流程中找到了一些解决方案,但是在多个流程之间做了这个呢?

任何想法都值得赞赏(注意:我不希望完全实现,我只需要更多的想法让我自己开始解决这个问题。)

1 个答案:

答案 0 :(得分:3)

您可以使用信号量(sem_init),它们可以在共享内存上运行。如果你想从不同的进程初始化信号量,那么它们也被命名为信号量(sem_open)。如果您需要与工作人员交换消息,例如将实际任务传递给他们,那么解决此问题的一种方法是使用POSIX message queues。它们被命名并在进程间工作。这是一个简短的例子。请注意,只有第一个工作线程实际初始化消息队列,其他线程使用现有线程的属性。此外,它(可能)保持持久,直到使用mq_unlink明确删除,为简单起见,我在此处跳过。

带工作线程的接收器

// Link with -lrt -pthread

#include <fcntl.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *receiver_thread(void *param) {
    struct mq_attr mq_attrs = { 0, 10, 254, 0 };

    mqd_t mq = mq_open("/myqueue", O_RDONLY | O_CREAT, 00644, &mq_attrs);
    if(mq < 0) {
        perror("mq_open");
        return NULL;
    }
    char msg_buf[255];
    unsigned prio;

    while(1) {
        ssize_t msg_len = mq_receive(mq, msg_buf, sizeof(msg_buf), &prio);
        if(msg_len < 0) {
            perror("mq_receive");
            break;
        }
        msg_buf[msg_len] = 0;
        printf("[%lu] Received: %s\n", pthread_self(), msg_buf);
        sleep(2);
    }
}

int main() {
    pthread_t workers[5];
    for(int i=0; i<5; i++) {
        pthread_create(&workers[i], NULL, &receiver_thread, NULL);
    }
    getchar();
}

<强>发件人

#include <fcntl.h>
#include <stdio.h>
#include <mqueue.h>
#include <unistd.h>

int main() {
    mqd_t mq = mq_open("/myqueue", O_WRONLY);
    if(mq < 0) {
        perror("mq_open");
    }
    char msg_buf[255];
    unsigned prio;

    for(int i=0; i<255; i++) {
        int msg_len = sprintf(msg_buf, "Message #%d", i);
        mq_send(mq, msg_buf, msg_len, 0);
        sleep(1);
    }
}