2011-02-14 236 views
17

我在Linux 2.6中。我有一个环境,其中2个进程通过消息传递模式的简单实现来模拟(使用共享内存)数据交换。通过使用mmap在进程之间共享内存

我有一个客户端进程(从父,这是服务器分叉),其与写入一个结构(消息),以创建的存储器映射区域(后叉):

message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

这然后将指针写入队列(以链表的形式)到另一个共享内存区域,该区域对于服务器和客户端进程是通用的(因为如果在fork之前创建了相同的代码)。然后服务器读取该区域,获取消息指针并对其进行处理。

的问题是,* m是fork()和当所述服务器进程试图访问被指向的存储器位置,得到了一个分割错误之后创建的。在客户端创建它之后,是否可以将该内存区域附加到服务器POST分叉?

注意:我不希望在分叉之前将指针指向消息(然后再与服务器共享),因为我通常不知道客户端要发送给服务器的消息数量,以及可能有超过1个客户端进程,所以我只想在客户端需要发送消息时创建一个新的共享内存块,并在服务器收到该消息后取消映射。

注意:这是为学术目的:我知道这是不是解决这个问题的最好办法,但我只需要按照这条道路。

在此先感谢!

回答

25

在客户端创建它之后,是否可以将该内存区域附加到服务器POST分叉?

MAP_ANONYMOUS|MAP_SHARED映射的内存只能被mmap()调用的进程或其子进程访问。另一个进程无法映射相同的内存,因为该内存不能从其他地方引用,因为它是匿名

使用shm_open()调用有可能创建名为共享内存,可以通过不相关的进程来引用和映射共享内存。

+0

谢谢!我用`shm_open()`然后用`mmap()`给出了fd,它部分地解决了这个问题。在fd是mmap之后,是否可以重命名(使用rename()`)我提供给`shm_open()`的“tag”字符串?我试过这样做,但后来,当我尝试从另一个使用重命名标记的进程使用`shm_open()`时,我得到一个运行时“总线错误”。 注意:我注意到在/ sys/shm /重命名文件存在,所以重命名似乎成功。 – 2011-02-14 16:25:12

6

这不起作用。

如果叉()之后创建一个映射,它不会在其他相关过程(ES)是相同的。

你不能假设指针以这种方式共享。如果你真的想这样做(我不推荐它!),你应该在fork()之前mmap一个大的区域,然后以某种方式分配合适大小的缓冲区(没有与其他进程的竞争条件当然!)并传递这些指针。

在fork之后调用mmap()的两个相关进程可能会得到相同的指针,指向不同的内存。事实上,这很可能。

1

仅供任何人在2018年及以后阅读此问题。 解决方案现在使用memfd_create创建匿名文件并使用unix套接字将此文件句柄传递给其他进程。

memfd_create是一个只有linux的系统调用