我需要将使用Windows API函数SetEvent
,CreateEvent
和WaitForMultipleObjects
的多进程应用程序移植到Linux。我找到了很多关于这个问题的主题,但没有一个为我的问题提供合理的解决方案。
我有一个应用程序,它分为三个进程,并通过这些事件管理一个进程的线程工作池。
我有多个解决方案来解决这个问题。一种是在Linux上使用mkfifo
在Linux上创建FIFO特殊文件,并使用select语句来唤醒线程。问题是此解决方案的运行方式与WaitForMultipleObjects
不同。例如,如果workerpool的10个线程将等待事件并且我调用SetEvent
五次,那么正好五个workerthreads将被唤醒并完成工作,当在Linux中使用FIFO变体时,它会唤醒每个线程,我在select语句中等待数据放入fifo。描述这种情况的最佳方式是Windows API类似于一个计数为1的全局信号量。
我还考虑过使用pthreads
和condition variables
重新创建并通过共享内存(shm_open
和mmap
)共享变量,但我遇到了同样的问题这里!
在Linux上重新创建此行为的合理方法是什么?我在一个流程中找到了一些解决方案,但是在多个流程之间做了这个呢?
任何想法都值得赞赏(注意:我不希望完全实现,我只需要更多的想法让我自己开始解决这个问题。)
答案 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);
}
}