首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >共享内存中的条件变量--这段代码符合POSIX吗?

共享内存中的条件变量--这段代码符合POSIX吗?
EN

Stack Overflow用户
提问于 2010-05-06 16:55:29
回答 3查看 11.5K关注 0票数 8

POSIX标准是否允许名为共享内存块包含互斥和条件变量?

我们一直试图使用互斥变量和条件变量来通过LynuxWorks LynxOS-SE系统上的两个进程(POSIX-一致性)来同步对命名共享内存的访问。

一个共享内存块称为"/sync",包含互斥和条件变量,另一个是"/data",包含我们同步访问的实际数据。

如果两个进程都没有以完全相同的顺序pthread_cond_signal()执行mmap()调用,或者一个进程在映射"/sync"内存之前映射到其他共享内存中,我们就会看到来自"/sync"的失败。

这个示例代码是我能做的最简短的代码:

代码语言:javascript
复制
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/file.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <iostream>
#include <string>
using namespace std;

static const string shm_name_sync("/sync");
static const string shm_name_data("/data");

struct shared_memory_sync
{
  pthread_mutex_t mutex;
  pthread_cond_t condition;
};

struct shared_memory_data
{
  int a;
  int b;
};


//Create 2 shared memory objects
// - sync contains 2 shared synchronisation objects (mutex and condition)
// - data not important 
void create()
{
  // Create and map 'sync' shared memory
  int fd_sync = shm_open(shm_name_sync.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
  ftruncate(fd_sync, sizeof(shared_memory_sync));
  void* addr_sync = mmap(0, sizeof(shared_memory_sync), PROT_READ|PROT_WRITE, MAP_SHARED, fd_sync, 0);
  shared_memory_sync* p_sync = static_cast<shared_memory_sync*> (addr_sync);

    // init the cond and mutex
  pthread_condattr_t cond_attr;
    pthread_condattr_init(&cond_attr);
    pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
    pthread_cond_init(&(p_sync->condition), &cond_attr);
    pthread_condattr_destroy(&cond_attr);

    pthread_mutexattr_t m_attr;
    pthread_mutexattr_init(&m_attr);
    pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&(p_sync->mutex), &m_attr);
    pthread_mutexattr_destroy(&m_attr);

  // Create the 'data' shared memory   
  int fd_data = shm_open(shm_name_data.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
  ftruncate(fd_data, sizeof(shared_memory_data));
  
  void* addr_data = mmap(0, sizeof(shared_memory_data), PROT_READ|PROT_WRITE, MAP_SHARED, fd_data, 0);
  shared_memory_data* p_data = static_cast<shared_memory_data*> (addr_data);

  // Run the second process while it sleeps here.
  sleep(10);

  int res = pthread_cond_signal(&(p_sync->condition));
  assert(res==0);  // <--- !ASSERT WILL FAIL ON LYNXOS!

  munmap(addr_sync, sizeof(shared_memory_sync));
  shm_unlink(shm_name_sync.c_str());
  munmap(addr_data, sizeof(shared_memory_data));
  shm_unlink(shm_name_data.c_str());
}

//Open the same 2 shared memory objects but in reverse order
// - data
// - sync 
void open()
{
  sleep(2);
  int fd_data = shm_open(shm_name_data.c_str(), O_RDWR, S_IRUSR|S_IWUSR);
  void* addr_data = mmap(0, sizeof(shared_memory_data), PROT_READ|PROT_WRITE, MAP_SHARED, fd_data, 0);
  shared_memory_data* p_data = static_cast<shared_memory_data*> (addr_data);

  int fd_sync = shm_open(shm_name_sync.c_str(), O_RDWR, S_IRUSR|S_IWUSR);
  void* addr_sync = mmap(0, sizeof(shared_memory_sync), PROT_READ|PROT_WRITE, MAP_SHARED, fd_sync, 0);
  shared_memory_sync* p_sync = static_cast<shared_memory_sync*> (addr_sync);

  // Wait on the condvar
  pthread_mutex_lock(&(p_sync->mutex));
  pthread_cond_wait(&(p_sync->condition), &(p_sync->mutex));
  pthread_mutex_unlock(&(p_sync->mutex));
  
  munmap(addr_sync, sizeof(shared_memory_sync));
  munmap(addr_data, sizeof(shared_memory_data));
}

int main(int argc, char** argv) 
{
  if(argc>1)
  {
    open(); 
  }
  else
  {
    create();
  }

    return (0);
}

运行此程序时不带args,然后再运行一个带有args的副本,第一个程序将在断言检查pthread_cond_signal()时失败。但是,将open()函数的顺序更改为mmap() "/sync“在"/data"之前的内存,这一切都会正常工作。

在我看来,这似乎是LynxOS中的一个主要缺陷,但LynuxWorks声称,在命名共享内存中使用互斥变量和条件变量的方式并不是POSIX标准所涵盖的,因此他们并不感兴趣。

有人能确定这段代码是否真的违反了POSIX吗?

或者,是否有人有任何令人信服的文件证明它符合POSIX?

编辑:我们知道PTHREAD_PROCESS_SHARED是POSIX,由LynxOS支持。争用的领域是互斥量和信号量是否可以在命名共享内存中使用(就像我们已经做的那样),或者如果POSIX只允许在一个进程创建和映射共享内存,然后分叉第二个进程时使用它们。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-05-11 08:30:02

我可以很容易地看到PTHREAD_PROCESS_SHARED如何在操作系统级别上实现是很棘手的(例如,MacOS没有实现,除了看起来是rwlock)。但从标准上看,你好像有案子。

为了完整起见,您可能需要断言(共享)和*_setpshared()函数调用的返回值--也许还有另一个“惊喜”在等着您(但我从注释中可以看到,您已经检查了该共享,它实际上是支持的)。

@JesperE:您可能希望引用OpenGroup上的API文档而不是HP文档。

票数 4
EN

Stack Overflow用户

发布于 2010-05-06 17:35:46

pthread_mutexattr_setpshared函数可用于允许任何访问该内存的线程,甚至不同进程中的线程,都可以访问共享内存中的线程互斥体。根据此链接pthread_mutex_setpshared符合POSIXP1003.1c。(条件变量也是如此,参见pthread_condattr_setpshared。)

相关问题:Linux上的p线程条件变量,奇怪的行为

票数 5
EN

Stack Overflow用户

发布于 2010-05-16 06:23:11

pthread_cond_t中可能有一些指针(没有pshared),所以您必须将它放在两个线程/进程中相同的地址中。使用相同顺序的mmap,您可以得到两个进程的相同地址。

在glibc中,cond_t中的指针指向线程的线程描述符,拥有mutex/cond。

可以使用非空第一个参数控制mmap的地址。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2782883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档