前言
进程间数据共享有很多实现方法,内存共享就是其中一种,大概思路是创建一块共享区域(这块区域用户可自定义名字),不同进程使用api将这块地址映射到自己的内存里,所以内存共享需要操作系统所支持,任何具体系统调用能力的语言都可以进行进程间内存共享,主流编程语言都具备此能力,而python下实现比较简单。
下面看一个例子。
写数据:
python
import mmap
import os
import time
if __name__ == "__main__":
mmap_file = mmap.mmap(0, 1024, access=mmap.ACCESS_WRITE, tagname='MySharedMemory')
for i in range(100):
mmap_file.write(str(i).encode('utf-8'))
print(i)
time.sleep(1)
mmap_file.seek(0)
tagname就是给内存起一个名字。
读数据
python
import mmap
import os
import time
if __name__ == "__main__":
mmap_file = mmap.mmap(0, 1024, access=mmap.ACCESS_READ, tagname='MySharedMemory')
for i in range(100):
mmap_file.seek(0)
data = mmap_file.read().translate(None,b'\x00').decode();
print(data)
time.sleep(1)
读数据时,他会读取到这块内存下所有的数据,如果我们不seek到头的话,读取完毕后会再也读不到数据,因为他已经到末尾了,同样每写一次数据时,他指向下一次写的位置就是发生下移,如果我们不seek到0的话,他效果就是内容追加,直到发送溢出。
python环境下如果你想知道进行了那些系统函数调用,可以使用api monitor
工具,如下图,其实就是调用了CreateFileMapping
和MapViewOfFile
这两个函数。
一个用来创建文件映射对象和将文件映射到进程的地址空间,所以说,内存共享就是文件的共享,只不过当文件对象参数传为INVALID_HANDLE_VALUE
时,不会创建文件,文档中所说这种情况会交给system paging file
去支持,这部分就不清楚了。
c 示例
下面是这两个函数的用法。
写入
c
#include <windows.h>
int main() {
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
100,
L"MySharedMemory");
LPVOID pData = MapViewOfFile(
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
100);
char source[] = "Hello, World!";
strcpy_s((char*)pData, 100, source);
Sleep(10000);
UnmapViewOfFile(pData);
CloseHandle(hMapFile);
return 0;
}
读取
c
#include <windows.h>
int main() {
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
100,
L"MySharedMemory");
LPVOID pData = MapViewOfFile(
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
100);
printf("data=%s\n",(char*)pData);
UnmapViewOfFile(pData);
CloseHandle(hMapFile);
return 0;
}
在c语言下,靠指针的移动来获取不同的数据,比如printf时,会打印目标char*
地址开始到结束符\0内的字符,如果内存中数据为abcde\0
,想获取bcde,将指针++
即可,比如上面代码,可通过(char*)pData++
来从下一个字节开始,从而忽略a
。