C ++ std lib <mutex>,<conditional_variable> libs和共享内存</conditional_variable> </mutex>

时间:2014-06-23 07:24:46

标签: c++ multithreading c++11

如果要在共享内存中的进程之间共享互斥锁,则需要设置特殊标志来设置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);
        }
    }

1 个答案:

答案 0 :(得分:4)

我使用类似的模式,但是,标准互斥锁和条件变量不是为了在进程之间共享而设计的。原因是POSIX需要在进程共享互斥锁和条件变量上设置PTHREAD_PROCESS_SHARED属性,但标准C ++原语不会这样做。在Windows上,它可能比这更复杂。

您可以尝试使用提升process shared mutexesprocess shared condition variables。或者为POSIX接口创建自己的包装器。


也可能是squeue破坏了缓冲区之外的内存,覆盖了struct SHM内存中的互斥锁和条件变量。我会尝试评论推送到队列中的代码,看看你是否仍然遇到了崩溃。我尝试使用队列代码注释掉你的代码,它按预期工作。


您可能还想使用condition_variable而不是condition_variable_any,因为后者保留了自己的互斥锁,但如果在锁定关联的互斥锁时通知该条件变量,则不需要该互斥锁(如你这样做。