在LynxOS/POSIX中,我该如何同步访问共享内存?

14

我正在一个采用LynxOS SE(符合POSIX标准)的系统上实现两个进程,它们将通过共享内存进行通信。

其中一个进程将充当“生产者”,另一个则是“消费者”。在多线程系统中,我的方法是使用互斥锁和条件变量对(mutex and condvar pair),其中消费者通过pthread_cond_wait等待条件变量,而生产者在更新共享内存时通过pthread_cond_signal发出信号。

那么在多进程而不是多线程的架构中,我该如何实现呢?

在LynxOS/POSIX中是否有创建可用于进程间的条件变量/互斥锁对的方法?或者在这种情况下是否有更适合的同步机制?


谢谢@nos,我注意到有一个pthread_condattr_setpshared但我错过了pthread_attr_setscope。如果您将您的评论更改为答案,我会点赞它。 - GrahamS
看起來我有點誤解了,pthread_condattr_setpshared 才是你應該使用的,pthread_attr_setscope 處理的是線程排程。 - nos
4个回答

28

感谢@nos,但我想对他的答案进行补充。
最终(为了清晰起见,不包括错误处理),我按照以下步骤进行:

1. 定义共享内存结构

这包含进程间同步对象和要共享的数据。

typedef struct
{
    // Synchronisation objects
    pthread_mutex_t ipc_mutex;
    pthread_cond_t  ipc_condvar;
    // Shared data
    int number;
    char data[1024];
} shared_data_t;

2. 创建共享内存并设置大小(主进程)

在主进程中创建一个新的共享内存对象:

fd = shm_open(SHAREDMEM_FILENAME, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
ftruncate(fd, sizeof(shared_data_t));

2. 或者打开共享内存(从进程)

在从进程中,只需附加到现有对象:

fd = shm_open(SHAREDMEM_FILENAME, O_RDWR, S_IRUSR|S_IWUSR);

3. 将mmap映射到进程空间中

// Specify addr of calling address, mostly use NULL is most portable way
shared_data_t* sdata = (shared_data_t*)mmap(NULL, sizeof(shared_data_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);

4. 初始化同步变量(仅适用于主进程)

pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&sdata->ipc_mutex, &mutex_attr);

pthread_condattr_t cond_attr;
pthread_condattr_init(&cond_attr);
pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&sdata->ipc_condvar, &cond_attr);

就这样。

互斥锁和条件变量现在可以像正常情况下一样用来控制对共享数据的访问。

唯一真正需要注意的是,在启动从进程之前,主进程必须创建共享内存并初始化同步变量。并确保您根据需要进行整理 munmap()shm_unlink()

注意:XSI备选方案

POSIX:XSI扩展具有其他用于共享内存的函数(shmget()shmat()等),如果它们可用,则可能更有用,但它们不适用于我正在使用的LynxOS-SE版本。


请注意:我们在LynxOS上使用这种方法时遇到了问题。 如果在此设置之前映射了任何其他内存,则会失败。 请参阅https://dev59.com/fk3Sa4cB1Zd3GeqPwqL-。 - GrahamS
1
在从进程的#2代码中,我在调用shm_open之后还必须调用ftruncate(fd,sizeof(shared_data_t))。对于#2,只是shm_open的参数在主进程和从进程之间有所不同。如果在从进程中没有ftruncate,则在尝试使用结构体末尾的可变数组成员时会出现EFAULT和其他错误。 - Bill Menees

8

使用未命名的POSIX信号量,与使用命名的POSIX信号量相比,是否有任何优势? - GrahamS
1
未命名的信号量在非竞争情况下,通过避免系统调用,在进程之间非常快速。 - Nikolai Fetissov

8
创建进程共享互斥锁/条件变量的标准方法是使用属性进行初始化,其中设置pthread_mutexattr_setpshared/pthread_condattr_setpshared。请检查LynxOS是否支持此功能。
您需要以某种方式将这些互斥锁/条件变量放置在共享内存中,以便所有进程都可以使用它。

谢谢@nos。我稍微扩展了一下你的答案。 - GrahamS

6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接