我需要将使用Windows API函数SetEvent,CreateEvent和WaitForMultipleObjects的多进程应用程序移植到Linux.我发现了许多与此问题有关的线程,但是没有一个线程为我的问题提供了合理的解决方案.
我有一个应用程序,它可以分为三个进程,并通过这些事件管理一个进程的线程工作池.
我对此问题有多种解决方案.一种是在Linux上使用mkfifo在FIFO上创建FIFO特殊文件,然后使用select语句唤醒线程.问题在于该解决方案的运行方式与WaitForMultipleObjects不同.例如,如果工作池中有10个线程将等待事件,而我调用SetEvent五次,则恰好五个工作线程将被唤醒并完成工作,在Linux中使用FIFO变体时,它将唤醒每个线程,即我在选择中语句并等待将数据放入fifo.描述此问题的最佳方法是Windows API的工作方式类似于一个计数为1的全局信号量.
我还考虑过使用pthreads和条件变量来重新创建它并通过共享内存(shm_open和mmap)共享变量,但是我在这里遇到了同样的问题!
在Linux上重新创建此行为的合理方法是什么?我发现有一些解决方案可以在单个流程中执行此操作,但是在多个流程之间执行此操作又如何呢?
任何想法都会受到赞赏(注意:我不希望有完整的实现,我只需要更多想法就可以开始解决此问题).
解决方法:
您可以使用信号量(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);
}
}