2017-10-15 89 views
1

如何在fork或子进程之后创建共享内存?如何在fork或子进程之后创建共享内存?

我想首先在共享内存中创建一个全局指针,然后在子进程中动态创建多个节点并将该节点添加到这个全局指针。

#include <string.h> 
#include <unistd.h> 

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 

struct shm_t { 
     int data; 
     struct shm_t *next; 
}; 

void main() { 
     struct shm_t *shm = (struct shm_t *)mmap(NULL, sizeof(*shm), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); 

     shm->data = 1; 
     shm->next = NULL; 

     int pid = fork(); 

     if (pid == 0) { 
       printf("Child \n"); 
       // How to create a shared shm_t here, and assign to *shm->next? 
     } else { 
       printf("Parent \n"); 
     } 
} 
+2

以这种小块分配共享内存效率非常低,并且会导致您快速耗尽。 –

+1

你最好分配一个大于你所需的数量,并实现你自己的分配器/释放器(使用'MADV_DONTNEED'来释放)。 – o11c

+0

@Ignacio是否有可能实现这一目标? – vego

回答

1

为了让两个进程共享内存,他们必须有一些共同点。

您的第一次分配是共享的,因为您将它分配给MAP_SHARED,并且子进程从父进程继承它。一旦分支已经完成,就没有办法自动发生这种情况(仅举一个例子:子进程与哪个进程共享?父进程只是一个随机进程,没有特别的意义,就Linux而言)。

正确执行此操作的方法是共享文件描述符。然而,这里陷阱的数量是惊人的。

让我们先从解决方案,然后再明白为什么它不会工作:

// Before the fork 
int shared_fd = open("/dev/shm/somefile", O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600); 
// Check for errors 
unlink("/dev/shm/somefile"); 
// check for errors 

// Now you can fork 

如果你现在使用mmap从这个文件,就可以在进程间共享(即 - 一个进程'写入对另一个进程是可见的)。

就像我说的,这里的陷阱的数量是巨大的:

  • 该文件被创建空的,你不能mmap过去文件的末尾。为了达到此目的,您需要使用ftruncate来增加文件。不过,这是一个问题。对ftruncate的调用需要同步,否则您将遇到丢失的更新问题,两个进程都认为他们将文件一起增加到相同的大小。
  • 即使你这样做后,你仍然不能存储内存中的指针。原因在于内存是共享的,因为一个进程的写入对另一个进程立即可见。但是,不能保证它们将映射到相同的地址。

我不确定你想在这里做什么(如果你想在两个进程之间共享一个链表,你也有巨大的同步问题来处理)。如果您可以提供您需要多少内存的先验限制,只需将它预先分配给原始的mmap即可。

然而,很可能你试图在这里实现的目标是不可能实现的(不以任何理智的方式)。

相关问题