加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

unix – 共享内存中的条件变量 – 此代码是否符合POSIX标准?

发布时间:2020-12-15 21:50:19 所属栏目:安全 来源:网络整理
导读:POSIX标准是否允许命名共享内存块包含互斥锁和条件变量? 我们一直在尝试使用互斥和条件变量来同步对LynuxWorks LynxOS-SE system(POSIX-conformant)上的两个进程对命名共享内存的访问. 一个共享内存块称为“/ sync”,包含互斥锁和条件变量,另一个是“/ data
POSIX标准是否允许命名共享内存块包含互斥锁和条件变量?

我们一直在尝试使用互斥和条件变量来同步对LynuxWorks LynxOS-SE system(POSIX-conformant)上的两个进程对命名共享内存的访问.

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

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

这个示例代码与我可以做的一样短:

#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(),S_IRUSR|S_IWUSR);
    ftruncate(fd_data,sizeof(shared_memory_data));

    void* addr_data = mmap(0,sizeof(shared_memory_data),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,0);
    shared_memory_data* p_data = static_cast<shared_memory_data*> (addr_data);

    int fd_sync = shm_open(shm_name_sync.c_str(),S_IRUSR|S_IWUSR);
    void* addr_sync = mmap(0,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()时失败.
但是在“/ data”之前将??open()函数的顺序更改为mmap()“/ sync”内存,它将全部正常工作.

这似乎是LynxOS中的一个主要错误,但是LynuxWorks声称在这个方式中使用这种方式在命名共享内存中使用互斥和条件变量不在POSIX标准中,所以他们不感兴趣.

任何人都可以确定此代码是否确实违反了POSIX?
或者有没有人有任何令人信服的文件证明它符合POSIX标准?

编辑:我们知道PTHREAD_PROCESS_SHARED是POSIX并且受LynxOS支持.争用的范围是可以在命名共享内存中使用互斥锁和信号量(正如我们所做的那样),或者当一个进程创建并映射共享内存然后分叉第二个进程时,POSIX只允许使用它们.

解决方法

我可以很容易地看到PTHREAD_PROCESS_SHARED如何在操作系统级别上实现起来很棘手(例如MacOS没有,除了rwlocks似乎).但只是从阅读标准,你似乎有一个案例.

为了完整起见,您可能希望在sysconf(_SC_THREAD_PROCESS_SHARED)上断言并且* _setpshared()函数的返回值调用 – 可能还有另一个“惊喜”等待您(但我可以从评论中看到您已经检查过实际支持SHARED) .

@JesperE:您可能想要参考API docs at the OpenGroup而不是HP文档.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读