python mmap进程内存共享实现原理

前言

进程间数据共享有很多实现方法,内存共享就是其中一种,大概思路是创建一块共享区域(这块区域用户可自定义名字),不同进程使用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工具,如下图,其实就是调用了CreateFileMappingMapViewOfFile这两个函数。

一个用来创建文件映射对象和将文件映射到进程的地址空间,所以说,内存共享就是文件的共享,只不过当文件对象参数传为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

相关推荐
BS30813_vx25 分钟前
基于 Express + uni-app 的养老院管理系统设计与实现
后端·uni-app·express
明月_清风36 分钟前
DeepSeek Harness 安全审计实录:四个 PoC 揭露的 Agent 运行时"信任危机"
后端·安全·agent
苏三说技术1 小时前
再见了EasyExcel,我决定用Apache Fesod
后端
XR1234567881 小时前
医院移动医护零漫游无线网络选型指南
java·后端·struts
ly76891 小时前
Spring Bean生命周期全流程:从BeanDefinition到销毁
java·后端·spring·bean生命周期·beandefinition·初始化回调
leeyi1 小时前
在 Go 里跑不信任的代码:WASM 沙箱的四道墙(第107篇)
后端
摇滚侠2 小时前
《Spring Boot 3:高级与架构设计》第 1 章 BeanDefinitionRegistry 阅读笔记 3
spring boot·笔记·后端
烂蜻蜓2 小时前
Flask入门教程(三十一):实用函数与类API——全局工具函数速查
后端·python·flask
计算机毕设定制辅导-无忧学长2 小时前
《基于Spring Boot传承之光非遗陶瓷烧造产品交易平台的设计与实现》
java·vue.js·spring boot·后端·毕业设计
Zane19942 小时前
内存都要回收,为什么JVM偏要把堆分成新生代和老年代
java·后端