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

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

所以,serverA启动并创build一个对象。 serverB启动并可以从serverA中的对象读取。

*编辑*

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

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

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

这种极其有限的共享forms在某些情况下仍然可以成为救星(虽然它非常有限):请记住,例如,添加对共享对象的引用会因为引用计数而“改变”该对象,所以会强制一个页面复制!)…除了在Windows上,当然,它不可用。 有了这个单一的例外(我不认为会覆盖你的用例),共享包含对其他对象的引用/指针的对象图的分享基本上是不可行的 – 几乎任何对现代语言感兴趣的对象(包括Python)属于这种分类。

在极端(但非常简单)的情况下,可以通过放弃这种对象图的本地内存表示来获得共享。 例如,每个有十六个浮点数的百万个元组的列表实际上可以被表示为一个128 MB的共享内存的单个块 – 所有的16M浮点都以双精度IEEE表示forms首尾相连 – 顶部“看起来像”你正在处理的东西在正常的方式(当然,不是那么一点一点的垫片也将不得不照顾的非常毛茸茸的进程间同步问题肯定会出现;-)。 从那里只会变得更加复杂和复杂。

现代的并发方法越来越不屑于共享任何方法,而不是无共享方法,其中任务通过消息传递进行通信(甚至在使用线程和共享地址空间的多核系统中,同步问题和性能击中了硬件在caching,pipe道延迟等方面,当多个内核被大量内存一次性主动修改时,就会把人推开)。

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

我意识到这对于OP来说不是一个好消息,但是如果他确实需要使用多个处理器才能工作,那么他最好考虑一下,他们必须共享的东西驻留在可以通过消息传递进行访问和修改的地方 – – 一个数据库,一个memcache集群,一个专门的进程,除了将这些数据保存在内存中并根据请求发送和接收它们,以及其他这样的以消息传递为中心的体系结构。

 mmap.mmap(0, 65536, 'GlobalSharedMemory') 

我认为标签(“GlobalSharedMemory”)对于所有希望共享相同内存的进程必须相同。

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

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

  • sysv_ipc
    • >适用于posix不符合标准的系统
  • posix_ipc
    • >使用cygwin在Windows中工作

这两个都可以通过点

[1]另一个包shm可用,但不推荐使用 。 看到这个页面来比较这些库。

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

shmwriter.c

 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> 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 

你可以编写一个C库来为你的特定目的创build和操作共享内存数组,然后使用ctypes从Python访问它们。

或者,把它们放在/ dev / shm(这是tmpfs)的文件系统上。 您可以节省大量的开发工作,但性能开销很小:从tmpfs文件系统读取/写入仅仅是memcpy。

为什么不将共享数据粘贴到memcache服务器? 那么两台服务器都可以很容易地访问它。

其实很简单。 你可以使用共享内存。 这个例子在C ++中创build了一个元组列表(python),并与一个可以使用元组列表的Python进程共享。 要在两个Python进程之间使用,只需在发送者进程ACCESS_WRITE访问权限设置为ACCESS_WRITE ,然后调用write方法。

C ++(发件人进程):

 #include <windows.h> #include <stdio.h> #include <conio.h> #include <tchar.h> #include <iostream> #include <string> #define BUF_SIZE 256 TCHAR szName[]=TEXT("Global\\MyFileMappingObject"); TCHAR szMsg[]=TEXT("[(1, 2, 3), ('a', 'b', 'c', 'd', 'e'), (True, False), 'qwerty']"); int _tmain(int argc, _TCHAR* argv[]) { HANDLE hMapFile; LPCTSTR pBuf; hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // use paging file NULL, // default security PAGE_READWRITE, // read/write access 0, // maximum object size (high-order DWORD) BUF_SIZE, // maximum object size (low-order DWORD) szName); // name of mapping object if (hMapFile == NULL) { _tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError()); return 1; } pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object FILE_MAP_ALL_ACCESS, // read/write permission 0, 0, BUF_SIZE); if (pBuf == NULL) { _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError()); CloseHandle(hMapFile); return 1; } CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR))); _getch(); UnmapViewOfFile(pBuf); CloseHandle(hMapFile); return 0; } 

Python(接收器进程):

 import mmap shmem = mmap.mmap(0,256,"Global\\MyFileMappingObject",mmap.ACCESS_READ) msg_bytes = shmem.read() msg_utf16 = msg_bytes.decode("utf-16") code = msg_utf16.rstrip('\0') yourTuple = eval(code) 

为什么不为共享数据使用数据库? 您有许多轻量级选项,您不必担心并发问题:sqlite,任何nosql /键值数据库等等。