C++ C++;标准库<;互斥锁>&书信电报;条件变量>;libs与共享内存

C++ C++;标准库<;互斥锁>&书信电报;条件变量>;libs与共享内存,c++,multithreading,c++11,C++,Multithreading,C++11,如果要在共享内存中的进程之间共享互斥,那么POSIX线程的C API需要设置一个特殊标志-请参阅sem_init()。我不知道这个差异是什么,但是在使用共享内存中的C++ STD::条件变量时,我遇到了麻烦——它的SEG错误。在C++文档或构造函数中,我看不到任何提及这一点。我想知道如何/如果你可以在共享内存中使用C++线程互斥体。这是我的测试代码供参考。注意squeue只是一个简单的(POD)静态大小的循环队列,忽略了不相关的内容: #include <iostream> #inc

如果要在共享内存中的进程之间共享互斥,那么POSIX线程的C API需要设置一个特殊标志-请参阅
sem_init()
。我不知道这个差异是什么,但是在使用共享内存中的C++ STD::条件变量时,我遇到了麻烦——它的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);
        }
    }
#包括
#包括
#包括模式常数的/**/
#对于O_*常数,包括/**/
#包括“squee.h”
#定义SHM_文件名“/shimmy foo”
#定义SQUEUE_长度10
类型定义结构{
挤压队列;
std::互斥互斥;
std::条件变量任意条件变量;
}SHM;
int main(){
int shm_fd=0;
SHM*SHM_ptr=NULL;
squeue*队列=NULL;
std::mutex*mutex;
std::条件变量condvar;
//Init SHM.ftruncate()将为零区域。
如果((shm_fd=shm_open(shm_FILENAME,O|u create | O|u RDWR | O|u EXCL,S|IREAD | S|u IWRITE))=-1){
fprintf(stderr,“无法打开shm对象。%s\n”,strerror(errno));
返回errno;
}
否则{
fprintf(标准,“打开shm OK.%d\n”,shm\u fd);
}
ftruncate(shm_fd,sizeof(shm));
//将shmptr指针连接到共享内存区域,
//具有所需的权限
如果((shm_ptr=(shm*)mmap(0,sizeof(shm),PROT_READ | PROT_WRITE,MAP_SHARED,shm_fd,0))==MAP_失败){
fprintf(stderr,“无法映射shm.%s\n”,strerror(errno));
返回errno;
}
否则{
fprintf(标准,“映射shm OK.%p\n”,shm_ptr);
}
//创建队列和互斥。
队列=新建(&shm_ptr->queue)队列();
mutex=new(&shm_ptr->mutex)std::mutex();
condvar=new(&shm_ptr->condvar)std::condition_variable_any();
srand(时间(空));
while(true){
cout full()){
int value=rand()%100;
队列->推送(值);

CUT< P>我使用了类似的模式,但是标准互斥和条件变量不是设计成在进程之间共享的。原因是POSIX需要在进程共享互斥和条件变量上设置代码> pthRead PosithySux.<代码>属性,但是标准C++原语不这样做。比那更复杂

您可以尝试使用boost和。或者为POSIX接口创建自己的包装器


也可能是
squeue
会破坏缓冲区以外的内存,覆盖互斥锁和
struct SHM
中内存中的条件变量。我会尝试注释推送到队列中的代码,看看是否仍然会发生崩溃。我用注释掉的队列代码尝试了您的代码,它可以作为exp反恐执行局



您可能还希望使用
条件变量
而不是
条件变量(any
),因为后者维护自己的互斥锁,但如果您在锁定相关互斥锁时通知该条件变量,则不需要该互斥锁(如您所做).

OK thx获得关于引用的建议。@stefen如果队列不在代码中,我几乎不必证明队列是无关的。这是一个非常简单的队列,我确信它与当前问题无关。@Francismpacon:这就是我要说的:如果它与错误无关,请完全删除它!不能使用非POD C共享内存中的++对象。@ N.M: Boo.IPC?有状态分配器吗?为什么我们要做所有这些工作,给出元组分配器扩展……伟大的“C++类不设置pthRead Palm Stand Stand”几乎就是我要找的答案。我用PTHeLeGy(COND互斥)的T替换了C++的东西,现在都在工作。