Unix 共享内存中的条件变量-此代码与POSIX一致吗?
POSIX标准是否允许名为的共享内存块包含互斥和条件变量 我们一直在尝试使用互斥体和条件变量,通过一个(POSIX一致性)上的两个进程同步对命名共享内存的访问 一个共享内存块称为Unix 共享内存中的条件变量-此代码与POSIX一致吗?,unix,ipc,posix,shared-memory,lynxos,Unix,Ipc,Posix,Shared Memory,Lynxos,POSIX标准是否允许名为的共享内存块包含互斥和条件变量 我们一直在尝试使用互斥体和条件变量,通过一个(POSIX一致性)上的两个进程同步对命名共享内存的访问 一个共享内存块称为“/sync”,包含互斥和条件变量,另一个是“/data”,包含我们正在同步访问的实际数据 如果两个进程在中执行mmap()调用的顺序不完全相同,或者如果一个进程在mmaps“/sync”内存之前在另一块共享内存中mmaps,我们就会看到pthread\u cond\u signal()的失败 此示例代码尽可能简短: #
“/sync”
,包含互斥和条件变量,另一个是“/data”
,包含我们正在同步访问的实际数据
如果两个进程在中执行mmap()
调用的顺序不完全相同,或者如果一个进程在mmaps“/sync”
内存之前在另一块共享内存中mmaps,我们就会看到pthread\u cond\u signal()
的失败
此示例代码尽可能简短:
#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); // <--- !!!THIS 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);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
静态常量字符串shm_name_sync(“/sync”);
静态常量字符串shm_name_data(“/data”);
结构共享内存同步
{
pthread_mutex_t mutex;
p线程条件;
};
结构共享内存数据
{
INTA;
int b;
};
//创建2个共享内存对象
//-同步包含2个共享同步对象(互斥和条件)
//-数据不重要
void create()
{
//创建并映射“同步”共享内存
int fd_sync=shm_open(shm_name_sync.c_str(),O_CREAT | O|u RDWR,S_IRUSR | S|u IWUSR);
ftruncate(fd_sync,sizeof(共享内存_sync));
void*addr\u sync=mmap(0,sizeof(共享内存同步),PROT\u READ | PROT\u WRITE,MAP\u shared,fd\u sync,0);
共享内存同步*p同步=静态同步(地址同步);
//初始化cond和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_mutextatr_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);
//创建“数据”共享内存
int fd_data=shm_open(shm_name_data.c_str(),O_CREAT | O|u RDWR,S_IRUSR | S|IWUSR);
ftruncate(fd_数据,sizeof(共享内存_数据));
void*addr_data=mmap(0,sizeof(共享内存数据),PROT_READ | PROT_WRITE,MAP_shared,fd_data,0);
共享内存数据*p数据=静态数据转换(添加数据);
//在第二个进程休眠时运行它。
睡眠(10);
int res=pthread_cond_信号(&(p_sync->condition));
断言(res==0);//互斥);
pthread_cond_wait(&(p_sync->condition),&(p_sync->mutex));
pthread_mutex_unlock(&(p_sync->mutex));
munmap(addr_sync,sizeof(共享内存同步));
munmap(addr_数据,sizeof(共享内存数据));
}
int main(int argc,字符**argv)
{
如果(argc>1)
{
open();
}
其他的
{
创建();
}
返回(0);
}
不使用args运行此程序,然后使用args运行另一个副本,第一个副本将在断言检查pthread\u cond\u signal()
时失败。
但是,将open()
函数的顺序更改为mmap()
在“/data”
之前的“/sync
”内存,所有操作都会正常工作
在我看来,这似乎是LynxOS中的一个主要错误,但LynuxWorks声称,POSIX标准不包括以这种方式在命名共享内存中使用互斥和条件变量,因此他们不感兴趣
有人能确定此代码是否确实违反POSIX吗?或者是否有人有任何令人信服的文档证明它符合POSIX Edit:我们知道
PTHREAD\u PROCESS\u SHARED
是POSIX,由LynxOS支持。争论的领域是互斥和信号量是否可以在命名共享内存中使用(正如我们所做的)或者,如果POSIX只允许在一个进程创建并映射共享内存,然后分叉第二个进程时使用它们。该函数可用于允许共享内存中的pthread mutex被任何有权访问该内存的线程访问,甚至是不同进程中的线程。根据pthread\u mutex\u setpshared符合POSIX P1003.1c。(条件变量也是如此,请参见pthread\u condattr\u setpshared
)
相关问题:我可以很容易地看出PTHREAD\u PROCESS\u SHARED在操作系统级别上的实现是多么棘手(例如,MacOS没有,除了看起来像是rBlock)。但仅仅从阅读标准来看,你似乎有一个理由 为了完整性,您可能希望断言*_setpshared()函数调用的on和返回值-可能还有另一个“惊喜”在等着您(但我可以从您已经检查过的注释中看出,实际上支持共享)
@JesperE:您可能希望参考而不是HP文档。可能在
pthread\u cond\t
中有一些指针(不带pshared),因此您必须将其放在两个线程/进程中相同的地址中。使用相同的有序MMAP,两个进程的地址可能相等
在glibc中,cond_t中的指针指向线程的线程描述符,拥有mutex/cond
您可以使用mmap的非空第一个参数控制地址。谢谢@JesperE,我知道
pthread\u mutex\u setpshared
和pthread\u PROCESS\u SHARED
是POSIX。我不认为LynuxWorks否认这一点。我认为争论更多的是关于我们创建互斥和condvar所在的共享内存的方式,例如,每个进程通过命名共享内存访问,而不是仅仅在一个进程中创建它,然后分叉来创建另一个。对不起,我读这个问题有点草率。手册页上说“这个选项允许任何访问互斥对象的线程对互斥对象进行操作