当前位置: 首页 > 后端技术 > Python

mmap用于本地进程间通信

时间:2023-03-26 11:20:06 Python

mmap基本原理网上关于mmap原理的资料很多,这里只简单介绍一下。mmap是内存映射的实现,就是把进程的虚拟地址空间映射到真实的物理内存上。因此,对映射地址的读写等同于对真实物理内存的读写,操作系统负责将写入的内容刷新到磁盘,或者从磁盘加载到内存(这里指的是文件映射,还有另一种称为匿名映射)。与传统IO的区别对于传统的IO调用,比如write(),CPU需要从用户态切换到内核态。操作系统内核负责将数据从用户进程地址空间复制到内核空间,然后将内核空间中的数据刷新到磁盘上,整个过程不仅需要CPU状态的切换,还不必要数据拷贝(将用户进程空间的数据拷贝到内核空间);mmap不是这样的。当调用mmap.write()时,相当于直接将数据复制到内核空间,然后由操作系统异步刷入磁盘。可以看出,mmap不仅减少了数据副本的数量,还提高了用户空间和内核空间之间数据交换的效率。用户进程不必阻塞和等待数据刷新到磁盘。read()系统调用也是如此。mmap的应用之一是本地进程间通信。进程通信的方式有很多种,如socket、管道、信号量、消息队列、mmap内存映射等。对于两个本地独立的进程,如果数据量很大,比如一个进程从一个进程中抓取视频流camera,将视频流拆分成图片,另一个进程识别图片的内容,每秒可能有几十帧图片,每张图片的大小可能达到几MB。这种场景下,最适合通过mmap内存映射的方式传输图片,效率会比较高。进程1将#8MBMAX_IMG_SIZE=8388608withopen(path,mode='wb+')asfile_obj,mmap.mmap(file_obj.fileno(),length=MAX_IMG_SIZE,access=mmap.ACCESS_WRITE)asmmap_obj:whileTrue:img=get_image()ifimg:shape=img.shape#图像的像素高度pixel_height_bytes=shape[0].to_bytes(byteorder='big',length=2)#图像的像素宽度pixel_width_bytes=shape[1].to_bytes(byteorder='big',length=2)img_bytes=img.tobytes()#图像字节长度img_length=len(img_bytes)img_length_bytes=img_length.to_bytes(byteorder='big',length=4)#写入图像mmap_obj[0:2]=pixel_height_bytesmmap_obj[2:4]=pixel_width_bytesmmap_obj[4:8]=img_length_bytesmmap_obj[8:8+img_length]=img_bytes#通知读取图像#...进程2读取#8MBMAX_IMG_SIZE=8388608withopen(path,mode='rb')asfile_obj,mmap.mmap(file_obj.fileno(),length=MAX_IMG_SIZE,access=mmap.ACCESS_READ)asmmap_obj:whileTrue:#接收读取通知pixel_height=int.from_bytes(mmap_obj[0:2],byteorder='big')pixel_width=int.from_bytes(mmap_obj[2:4],byteorder='big')img_length=int.from_bytes(mmap_obj[4:8],byteorder='big')img_byte=mmap_obj[8:8+img_length]nparr=np.frombuffer(img_byte,dtype=np.uint8)img=nparr.reshape((pixel_height,pixel_width,3))