尝试从两个不同的进程锁定共享内存时,为什么pthread_mutex_t会出现段错误?

Pal*_*han 5 c++ multithreading pthreads shared-memory

我为pthread_mutex_t编写了一个超级简单的包装器,用于在两个进程之间使用:

//basic version just to test using it between two processes
struct MyLock
{
    public:
        MyLock() {
            pthread_mutexattr_init(&attr);
            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);

            pthread_mutex_init(&lock, &attr);
        }

        ~MyLock() {
            pthread_mutex_destroy(&lock);
            pthread_mutexattr_destroy(&attr);
        }

        lock() {
            pthread_mutex_lock(&lock);
        }

        unlock() {
            pthread_mutex_unlock(&lock);
        }

    private:
        pthread_mutexattr_t attr;
        pthread_mutex_t lock;
};
Run Code Online (Sandbox Code Playgroud)

我能够看到这个锁在一个进程中的常规线程之间正常工作,但是当我运行进程A时,它在共享内存区域中执行以下操作:

void* mem; //some shared memory from shm_open
MyLock* myLock = new(mem) MyLock;
//loop sleeping random amounts and calling ->lock and ->unlock
Run Code Online (Sandbox Code Playgroud)

然后进程B打开共享内存对象(通过设置它与内存的相同区域的字符组合进行验证)并执行以下操作:

MyLock* myLock = reinterpret_cast<MyLock*>(mem);
//same loop for locking and unlocking as process A
Run Code Online (Sandbox Code Playgroud)

但是当尝试使用backpce锁定导致libpthread.so.0中的pthread_mutex_lock()时,进程B会出现段错误

我究竟做错了什么?

我从流程B得到的回溯看起来像这样:

in pthread_mutex_lock () from /lib64/libpthread.so.0
in MyLock::lock at MyLock.H:50
in Server::setUpSharedMemory at Server.C:59
in Server::Server at Server.C
in main.C:52
Run Code Online (Sandbox Code Playgroud)

该调用是在重新解释将内存转换为内存之后的第一次锁定调用MyLock*.如果我在崩溃过程中将myLock的内容转储到gdb中,我看到:

{
attr = {
    __size = "\003\000\000\200",
    __align = -2147483645
},
lock = {
    __data = {
      __lock = 1
      __count = 0,
      __owner = 6742, //this is the lightweight process id of a thread in process A
      __nusers = 1,
      __kind = 131,
      __spins = 0,
      __list = {
        __prev = 0x0,
        __Next = 0x0
       }
      },
      __size = "\001\000\000\000\000 //etc,
      __align = 1     
  }
}
Run Code Online (Sandbox Code Playgroud)

所以它看起来没问题(在其他进程gdb中看起来也是如此).我正在使用没有额外的优化标志来编译两个应用程序.

nod*_*kai 3

您没有发布打开和初始化共享内存区域的代码,但我怀疑该部分可能会导致您的问题。

因为pthread_mutex_t比“字符组合”大得多,所以您应该通过读取和写入更长 (~ KB) 的字符串来检查您的shm_open(3)--序列。ftruncate(2)mmap(2)

不要忘记检查两个端点是否确实可以写入 shm 区域,并且写入的数据对于另一端是否确实可见。

流程A:[打开并初始化shm]-[写入AAA...AA]-[睡眠5秒]-[读取BBB...BB]-[关闭thm]

进程B:(一两秒后)[打开shm]-[读取AAA...AA]-[写入BBB...BB]-[关闭thm]