通过使用 mmap() 在进程之间共享内存
我使用的是Linux 2.6。我有一个环境,其中两个进程通过消息传递模式的简单实现来模拟(使用共享内存)数据交换。
我有一个客户端进程(从父级(即服务器)分叉),它将结构(消息)写入创建的内存映射区域(分叉后):
message *m = mmap(NULL, sizeof(message ) ), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)
然后将该指针写入队列(以链表的形式)到服务器和客户端进程共用的另一个共享内存区域(因为如果是在 fork 之前使用上面相同的代码创建的)。然后服务器读取该区域,获取消息的指针并对其进行处理。
问题是 *m 是在 fork() 之后创建的,当服务器进程尝试访问指向的内存位置时,我收到分段错误。在客户端创建该内存区域后,是否可以将其附加到服务器 POST 分叉?
注意:我不想在分叉之前将指针映射到消息(然后事先与服务器共享),因为我通常不知道客户端想要发送多少消息到服务器,而且可能还有更多消息超过 1 个客户端进程,因此我想仅在客户端需要发送消息时创建一个新的共享内存块,并在服务器收到该消息后取消映射它。
注意:这是出于学术目的:我知道这不是解决这个问题的最佳方法,但我只需要遵循这条路径。
提前致谢!
I'm in Linux 2.6. I have an environment where 2 processes simulate (using shared memory) the exchange of data through a simple implementation of the message passing mode.
I have a client process (forked from the parent, which is the server) which writes a struct(message) to a memory mapped region created (after the fork) with:
message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)
This pointer is then written to a queue (in form of a linked list) into another shared memory area which is common to server and client process (because if was created prior to fork with the same code above). This area is then read by the server which obtains the pointer to the message and processes it.
The problem is that *m is created after the fork() and when the server process tries to access the pointed memory location, i get a segmentation error. Is it possible to attach that region of memory to the server POST forking, after the client creates it?
NOTE: I don't want to mmap the pointer to message before forking (and then sharing it prior with the server) because I typically don't know how many messages the client wants to send to the server, and also there may be more than 1 client process, so I'd like to create a new block of shared memory only when a client needs to send a message, and unmap it after the server has received that message.
NOTE: This is for academic purpose: I know this is not the best way to solve this problem, but I just need to follow this path.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
MAP_ANONYMOUS|MAP_SHARED
映射内存只能由执行mmap()
调用的进程或其子进程访问。另一个进程无法映射相同的内存,因为该内存无法从其他地方引用,因为它是匿名的。使用
shm_open()
调用可以创建命名共享内存,该内存可以被不相关的进程引用和映射。MAP_ANONYMOUS|MAP_SHARED
mapped memory can only be accessed by the process which does thatmmap()
call or its child processes. There is no way for another process to map the same memory because that memory can not be referred to from elsewhere since it is anonymous.Using
shm_open()
call it is possible to create named shared memory which can be referred to and mapped by unrelated processes.仅供 2018 年及以后阅读此问题的人参考。
现在的解决方案是使用 memfd_create 创建一个匿名文件,并使用 unix 套接字将此文件句柄传递给其他进程。
memfd_create 是仅限 Linux 的系统调用
Just for anyone reading this question in 2018 and later.
The solution is now to use memfd_create to create an anonymous file and use a unix socket to pass this file handle to the other process.
memfd_create is a linux only syscall
那是行不通的。
如果您在 fork() 之后创建映射,则它在其他相关进程中将不一样。
您不能假设以这种方式共享指针。
如果你真的想这样做(我不推荐它!),你应该在 fork() 之前映射一个大区域,然后以某种方式分配合适大小的缓冲区(当然,没有与其他进程的竞争条件!) )并传递这些指针。
在 fork 之后调用 mmap() 的两个相关进程可能会返回指向不同内存的相同指针。事实上这种可能性极大。
That's not going to work.
If you create a mapping after the fork(), it won't be the same in the other related process(es).
You can't assume the sharing of pointers in this way.
If you really want to do it this way (I would not recommend it!), you should mmap a big area before the fork(), then allocate somehow, buffers of a suitable size (without race conditions with other processes, of course!) and pass those pointers.
Two related processes which call mmap() after a fork, may get the same pointer back, pointing at different memory. In fact this is extremely likely.