如果要在共享内存中的进程之间共享互斥锁,则需要设置特殊标志来设置POSIX线程的C API - 请参阅sem_init()
。我真的不知道差异是什么,但我在共享内存中尝试使用C ++ std :: condition_variable时遇到了麻烦 - 它的seg错误。我在C ++文档或构造函数中看不到任何提及此内容的东西。我想知道如何/如果你可以在共享内存中使用C ++线程互斥。这是我的测试代码供参考。注意squeue
只是一个简单的(POD)静态大小的循环队列,省略了不相关的东西:
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include "squeue.h"
#define SHM_FILENAME "/shimmy-foo"
#define SQUEUE_LENGTH 10
typedef struct {
squeue<int,SQUEUE_LENGTH> queue;
std::mutex mutex;
std::condition_variable_any condvar;
} SHM;
int main() {
int shm_fd = 0;
SHM * shm_ptr = NULL;
squeue<int,SQUEUE_LENGTH> * queue = NULL;
std::mutex * mutex;
std::condition_variable_any * condvar;
// Init SHM. ftruncate() will zero area.
if((shm_fd = shm_open(SHM_FILENAME, O_CREAT|O_RDWR|O_EXCL, S_IREAD|S_IWRITE)) == -1 ) {
fprintf (stderr, "Could not open shm object. %s\n", strerror(errno));
return errno;
}
else {
fprintf (stderr, "Open shm OK. %d\n", shm_fd);
}
ftruncate(shm_fd, sizeof(SHM));
// Connect the shmptr pointer to set to the shared memory area,
// with desired permissions
if((shm_ptr = (SHM*)mmap(0, sizeof(SHM), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
fprintf (stderr, "Could not map shm. %s\n", strerror(errno));
return errno;
}
else {
fprintf(stderr, "Mapped shm OK. %p\n", shm_ptr);
}
// Create queue and mutex.
queue = new(&shm_ptr->queue) squeue<int,SQUEUE_LENGTH>();
mutex = new(&shm_ptr->mutex) std::mutex();
condvar = new(&shm_ptr->condvar) std::condition_variable_any();
srand(time(NULL));
while(true) {
cout << "Waiting on lock" << endl;
mutex->lock();
if(!queue->full()) {
int value = rand()%100;
queue->push(value);
cout << "Pushed " << value << endl;
} else {
cout << "Que is full!" << endl;
};
condvar->notify_all(); //Seg fault.
mutex->unlock();
sleep(1);
}
}
答案 0 :(得分:4)
我使用类似的模式,但是,标准互斥锁和条件变量不是为了在进程之间共享而设计的。原因是POSIX需要在进程共享互斥锁和条件变量上设置PTHREAD_PROCESS_SHARED
属性,但标准C ++原语不会这样做。在Windows上,它可能比这更复杂。
您可以尝试使用提升process shared mutexes和process shared condition variables。或者为POSIX接口创建自己的包装器。
也可能是squeue
破坏了缓冲区之外的内存,覆盖了struct SHM
内存中的互斥锁和条件变量。我会尝试评论推送到队列中的代码,看看你是否仍然遇到了崩溃。我尝试使用队列代码注释掉你的代码,它按预期工作。
您可能还想使用condition_variable
而不是condition_variable_any
,因为后者保留了自己的互斥锁,但如果在锁定关联的互斥锁时通知该条件变量,则不需要该互斥锁(如你这样做。