POSIX標準允許名爲共享內存塊包含互斥和條件變量嗎?共享內存中的條件變量 - 此代碼是否符合POSIX標準?
我們一直試圖使用一個互斥鎖和條件變量來同步兩個進程(POSIX-conformant)上的兩個進程對命名共享內存的訪問。
一個共享內存塊被稱爲"/sync"
幷包含互斥鎖和條件變量,另一個是"/data"
幷包含我們正在同步訪問的實際數據。
我們從pthread_cond_signal()
看到失敗,如果這兩個過程不執行mmap()
電話完全相同的順序,或者如果在一個過程mmaps其他一些一塊共享內存的它mmaps的"/sync"
內存之前。
這個例子的代碼是關於儘可能短,我可以把它:
#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);
}
運行此程序與無參數,然後另一個副本ARGS,並第一個將在斷言檢查pthread_cond_signal()
失敗。 但open()
功能的順序更改爲mmap()
的"/data"
前"/sync
「的內存和它都做工精細。
這似乎是在LynxOS的給我一個大錯誤,但LynuxWorks公司聲稱,使用內互斥和條件變量以這種方式命名的共享內存不被POSIX標準所覆蓋,所以他們不感興趣。
任何人都可以判斷這段代碼實際上確實違反POSIX?
或任何人有任何令人信服的記錄,這是POSIX兼容?
編輯:我們知道PTHREAD_PROCESS_SHARED
是POSIX,並且由LynxOS支持。爭用的領域是互斥鎖和信號量是否可以在命名共享內存中使用(就像我們已經完成的一樣),或者POSIX只允許在一個進程創建時使用它們,然後映射共享內存,然後分叉第二個進程。
我不知道他們究竟是如何想象共享兩個進程之間使用PTHREAD_PROCESS_SHARED相同的變量(這顯然意味着*的共享流程之間的可變部分*機制應該存在的。)而據我所知沒有標準禁止將互斥和信號燈無論你是否想,所以「未覆蓋」意味着「應該照常運行」。 – 2017-06-01 08:31:08