当前位置:  开发笔记 > 编程语言 > 正文

可以在两个独立的进程之间共享内存数据吗?

如何解决《可以在两个独立的进程之间共享内存数据吗?》经验,为你挑选了3个好方法。

我有一个使用Twisted的xmlrpc服务器.服务器有大量的数据存储在内存中.是否可以运行一个辅助的单独的xmlrpc服务器,它可以访问第一个服务器中的内存中的对象?

因此,serverA启动并创建一个对象.serverB启动并可以从serverA中的对象读取.

*编辑*

要共享的数据是一百万个元组的列表.



1> Alex Martell..:

如果没有深入和暗淡地重写Python核心运行时(为了允许强制使用给定的共享内存段并确保不同进程之间的兼容地址的分配器),就无法在任何一般意义上"共享内存中的对象".该列表将保存一百万个元组地址,每个元组由其所有项目的地址组成,并且这些地址中的每一个都将由pymalloc以一种不可避免地在进程之间变化并在整个堆中传播的方式分配.

在除了Windows之外的几乎所有系统上,只要父进程不改变那些对象,就可以生成一个对父进程空间中的对象具有基本只读访问权限的子进程.这是通过调用获得的os.fork(),在实践中"快照"当前进程的所有内存空间并在复制/快照上启动另一个同时进程.在所有现代操作系统上,由于"写入时复制"方法,这实际上非常快:虚拟内存的页面在fork之后没有被任何进程更改,而是没有真正复制(相同页面的访问是共享的) ; 只要任一进程修改先前共享页面中的任何位,poof,该页面被复制,并且页面表被修改,因此修改过程现在具有其自己的副本,而另一个进程仍然看到原始副本.

在某些情况下,这种极其有限的共享形式仍然可以成为救星(尽管它非常有限:请记住,例如,由于引用计数,添加对共享对象的引用会被视为"更改"该对象,因此会强制页面复制!)...除了在Windows上,当然,它不可用.有了这个例外(我认为不会涵盖你的用例),共享包含对其他对象的引用/指针的对象图基本上是不可行的 - 几乎任何对现代语言感兴趣的对象(包括Python)属于这种分类.

在极端(但足够简单)的情况下,可以通过放弃这种对象图的本机存储器表示来获得共享.例如,一个包含十六个浮点数的一百万个元组的列表实际上可以表示为128 MB共享内存的单个块 - 所有16M浮点数都是双精度IEEE表示的端到端放置 - 有一些小垫片顶部"使它看起来像"你正在以正常的方式处理事物(当然,不那么小的一点一点的垫片也必须处理极其毛茸茸的进程间同步问题,肯定会出现;-).从那里开始它只会变得更加毛茸茸.

现代的并发方法越来越蔑视共享 - 任何方法都支持无共享方式,其中任务通过消息传递进行通信(即使在使用线程和共享地址空间的多核系统中,同步问题和性能也会遇到硬件)在缓存,流水线档位等方面,当大面积的内存被多个内核同时主动修改时,会推动人们离开).

例如,Python标准库中的多处理模块主要依赖于酸洗和来回发送对象,而不是共享内存(当然不是以R/W方式! - ).

我意识到这对OP来说不是一个受欢迎的新闻,但如果他确实需要将多个处理器用于工作,那么他最好考虑一下他们必须共享的任何内容,以便可以通过消息传递来访问和修改它们 - - 数据库,内存缓存集群,一个专门的进程,除了将这些数据保存在内存中并根据请求发送和接收它们之外什么都不做,以及其他这样的以消息传递为中心的体系结构.


多么有见地的答案!谢谢Alex.但是有一种情况需要在进程之间共享数据,主要是为了最大化访问速度,同时最小化内存消耗.这篇文章建议multiprocess.Array.http://stackoverflow.com/questions/10721915/shared-memory-objects-in-python-multiprocessing

2> Joe Koberg..:
mmap.mmap(0, 65536, 'GlobalSharedMemory')

我认为对于希望共享相同内存的所有进程,标记("GlobalSharedMemory")必须相同.

http://docs.python.org/library/mmap.html


我想你必须挑选(或类似编码)你想要分享的任何东西.

3> DylanYoung..:

有一对夫妇1第三方库可用于Python中低级别的共享内存的操作:

sysv_ipc

>对于posix不兼容系统

posix_ipc

>在Windows中使用cygwin

这两个都可以通过pip获得

[1]另一个软件包,shm,可用,但已弃用.有关库的比较,请参阅此页面.

C到Python通信的示例代码c/o Martin O'Hanlon:

shmwriter.c

#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, const char **argv)
{
   int shmid;
   // give your shared memory an id, anything will do
   key_t key = 123456;
   char *shared_memory;

   // Setup shared memory, 11 is the size
   if ((shmid = shmget(key, 11, IPC_CREAT | 0666)) < 0)
   {
      printf("Error getting shared memory id");
      exit(1);
   }
   // Attached shared memory
   if ((shared_memory = shmat(shmid, NULL, 0)) == (char *) -1)
   {
      printf("Error attaching shared memory id");
      exit(1);
   }
   // copy "hello world" to shared memory
   memcpy(shared_memory, "Hello World", sizeof("Hello World"));
   // sleep so there is enough time to run the reader!
   sleep(10);
   // Detach and remove shared memory
   shmdt(shmid);
   shmctl(shmid, IPC_RMID, NULL);
}

shmreader.py

import sysv_ipc

# Create shared memory object
memory = sysv_ipc.SharedMemory(123456)

# Read value from shared memory
memory_value = memory.read()

# Find the 'end' of the string and strip
i = memory_value.find('\0')
if i != -1:
    memory_value = memory_value[:i]

print memory_value

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有