1.概述

共享内存可以说是最有用的进程间通信方式.两个不同的进程共享内存的意思是:同一块物理内存被映射到两个进程的各自的进程地址空间.一个进程可以及时看到另一个进程对共享内存的更新,反之亦然.采用共享内存通信的一个显而易见的好处效率高,因为进程可以直接读写内存,而不需要任何数据的复制.对于向管道和消息队列等通信等方式,则需要在内核和用户空间进行四次的数据复制,而共享内存则只需要两次数据复制:一次从输入文件到共享内存区,另一个从共享内存区到输出文件.实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域.而是保持共享区域,知道通信完毕为止,这样,数据内容就一直保存在共享内存中,并没有写回文件.共享内存中的内容往往是在解除映射时才写回文件的.因此,采用共享内存的通信方式效率非常高.

mmap系统调用是的是的进程间通过映射同一个普通文件实现共享内存.普通文件被映射到进程地址空间后,进程可以向像访问普通内存一样对文件进行访问,不必再调用read,write等操作.与mmap系统调用配合使用的系统调用还有munmap,msync等. 实际上,mmap系统调用并不是完全为了用于共享内存而设计的.它本身提供了不同于一般对普通文件的访问方式,是进程可以像读写内存一样对普通文件操作.而Posix或System V的共享内存则是纯粹用于共享内存的,当然mmap实现共享内存也是主要应用之一.

2. python mmap模块详解

在python中,mmap.mmap()的函数实现在windows和linux上是不一样的,但实现api接口函数很相似,下面以mmap的windows实现为例说明:

mmap.mmap(fileno, length[, tagname[, access[, offset]]])

fileno:the file handle fileno, 文件描述符

length:共享内存的大小

tagname: 共享内存区域的名字,可以理解为id

access:

ACCESS_READ: 只能读,如果执行写操作,raises a TypeError exception

ACCESS_WRITE: 可读可写

ACCESS_COPY: 可读可写,但不更新到文件中去

函数列表

mmap.close() 断开映射关系

mmap.find(string[, start[, end]]):返回第一个string的索引,否则返回-1

mmap.move(dest, src, count): 移动count大小的内容从src到dest

mmap.read(num): 根据文件指针的位置兑取num个字节的内容,更新文件指针的位置

mmap.read_byte():读取当前字符,更新文件指针位置

mmap.readline():Returns a single line, starting at the current file position and up to the next newline.从当前位置到下一行位置的所有内容

mmap.resize(newsize):Resizes the map and the underlying file,改变映射内存与文件大小

mmap.rfind(string[, start[, end]]): 返回最后一个string的索引

mmap.seek(pos[, whence]): 设置文件指针的位置

mmap.size(): 返回共享内存的大小

mmap.tell():返回当前指针的位置

mmap.write(string):从当前指针位置开始写入string

mmap.write_byte(byte): Write the single-character string byte into memory at the current position of the file pointer; the file position is advanced by 1.

3.基于mmap和json实现内存共享

ObjectMmap继承自mmap,结合json实现python obj的共享

jsonwrite(obj): 将可json序列化的obj对象写入共享内存

jsonread_master():主进程获取内存内容

jsonread_follower(): 从进程获取内存内容

自定义的jsonmmap模块:

#!/usr/bin/python

# -*- coding: utf-8 -*-

import mmap

import json

class ObjectMmap(mmap.mmap):

def __init__(self, fileno=-1, length=1024, access=mmap.ACCESS_WRITE, tagname='share_mmap'):

super(ObjectMmap, self).__init__(self, fileno, length, access=access, tagname=tagname)

self.length = length

self.access = access

self.tagname = tagname

def jsonwrite(self, obj):

try:

self.obj = obj

obj_str = json.dumps(obj)

obj_len = len(obj_str)

content = str(obj_len) + ":" + obj_str

self.write(content)

self.contentbegin = len(str(obj_len)) + 1

self.contentend = self.tell()

self.contentlength = self.contentend - self.contentbegin

return True

except Exception, e:

return False

def jsonread_master(self):

try:

self.seek(self.contentbegin)

content = self.read(self.contentlength)

obj = json.loads(content)

self.obj = obj

return obj

except Exception, e:

if self.obj:

return self.obj

else:

return None

def jsonread_follower(self):

try:

index = self.find(":")

if index != -1:

head = self.read(index + 1)

contentlength = int(head[:-1])

content = self.read(contentlength)

obj = json.loads(content)

self.obj = obj

return obj

else:

return None

except Exception, e:

if self.obj:

return self.obj

else:

return None

4.举例

主进程:

#!/usr/bin/python

# -*- coding: utf-8 -*-

import mmap

from jsonmmap import ObjectMmap

import random

def main():

mm = ObjectMmap(-1, 1024*1024, access=mmap.ACCESS_WRITE, tagname='share_mmap')

while True:

length = random.randint(1, 100)

p = range(length)

mm.jsonwrite(p)

print '*' * 30

print mm.jsonread_master()

if __name__ == '__main__':

main()

从进程:

#!/usr/bin/python

# -*- coding: utf-8 -*-

import mmap

from jsonmmap import ObjectMmap

import time

def main():

mm = ObjectMmap(-1, 1024*1024, access=mmap.ACCESS_READ, tagname='share_mmap')

while True:

print '*' * 30

print mm.jsonread_follower()

if __name__ == '__main__':

main()

5.应用场景

主进程+多个从进程,主进程负责管理多个从进程,主从进程共享一个可序列化json对象,譬如说共享配置; 主进程才具备权限去修改配置,从进程仅仅具备访问权限。

import mmap

mmap_file = None

##从内存中读取信息,def read_mmap_info():

global mmap_file

mmap_file.seek(0)

##把二进制转换为字符串 info_str=mmap_file.read().translate(None, b'\x00').decode()

print(info_str)##如果内存中没有对应信息,则向内存中写信息以供下次调用使用def get_mmap_info():

global mmap_file

##第二个参数1024是设定的内存大小,单位:字节。如果内容较多,可以调大一点 mmap_file = mmap.mmap(-1, 1024, access = mmap.ACCESS_WRITE, tagname = 'share_mmap')

##读取有效比特数,不包括空比特 cnt=mmap_file.read_byte()

if cnt==0:

print("Load data to memory")

mmap_file = mmap.mmap(0, 1024, access = mmap.ACCESS_WRITE, tagname = 'share_mmap')

mmap_file.write(b"This is the test data")

else :

print("The data is in memory")

read_mmap_info()

##修改内存块中的数据def reset_mmp_info:

global mmap_file

mmap_file.seek(0)

mmap_file.write(b'\x00')

mmap_file.write(b"Load data to memory agine")

if __name__=="__main__":

get_mmap_info()

说明:如果是使用python自带的IDE,请重新打开一次此文件运行测试数据装载到内存后的结果

简单进程通信案例

#########################################################

#writer

import win32event as w32e

import mmapfile as mmf

#hEvent = w32e.OpenEvent(w32e.EVENT_ALL_ACCESS , 0 , "KaiMemEvent") #"Global\\JmdebuggerEvent"

pyMm = mmf.mmapfile(None , "KaiMem" ,1024)

hEvent = 1

if hEvent != None and pyMm != None:

#w32e.SetEvent(hEvent)

pyMm.write("hello world again!");

#############################################################

#reader

import win32event as w32e

import win32api as wapi

import mmapfile as mmf

#hEvent = w32e.CreateEvent(w32e.EVENT_ALL_ACCESS , 0 , 0 , "KaiMemEvent") #

#system_info=wapi.GetSystemInfo()

#page_size=system_info[1]

pyMm = mmf.mmapfile(None , "KaiMem" ,1024 )

hEvent = 1

if hEvent != None and pyMm != None :

#w32e.WaitForSingleObject(hEvent , -1)

buf = pyMm.read(22)

print buf

#wapi.CloseHandle(hEvent)

pyMm.close()

python slice是共享内存吗_python共享内存实现进程通信相关推荐

  1. python 多进程 内存增长_python 多进程 内存 copy-on-write

    由于python  中有个GIL 的东西,所使用的线程 python线程对于  cpu密集型的应用是没有作用的   对于io密集型的应用可以体现价值.如果想要利用多核就得使用多进程编程. python ...

  2. 什么是python语言的动态类型机制_python的内存管理机制

    一.python是一个什么样类型的语言 1.python是一种动态解释性强类型定义的高级.通用性编程语言. 解释型:执行的时候,才一条一条的解释成机器语言给计算机来执行.如:python.js.rub ...

  3. python 内存溢出_Python之内存泄漏和内存溢出

    一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...

  4. python slice start比end小_Python入门

    注释 单行注释使用符号(#) #print(hello world) 多行注释可以使用符号("') ''' print(hello world) ''' 代码换行 如果代码是在过长,需要换行 ...

  5. 限制python内存上限_Python限制内存和CPU使用量的方法(Unix系统适用)

    问题 你想对在Unix系统上面运行的程序设置内存或CPU的使用限制. 解决方案 resource 模块能同时执行这两个任务.例如,要限制CPU时间,可以像下面这样做: import signal im ...

  6. python读取大文件csv内存溢出_Python,内存错误,csv文件太大

    我有一个python模块的问题,它不能处理导入大数据文件(文件目标.csv重量接近1 Gb) 加载此行时出现错误:targets = [(name, float(X), float(Y), float ...

  7. python slice函数画高维图_Python 绘制 3 维以上的高维图

    实用技巧. 我们的大脑通常最多能感知三维空间,超过三维就很难想象了.尽管是三维,理解起来也很费劲,所以大多数情况下都使用二维平面.不过,我们仍然可以绘制出多维空间,今天就来用 Python 的 plo ...

  8. python slice start比end小_Python - lambda与内置函数

    lambda的表达式 对于简单的函数,也存在一种简便的表示方式,即:lambda表达式 #普通函数 def func(a): return a+1 print ('test1_func0:',func ...

  9. python多线程和异步性能对比_python对比线程,进程,携程,异步,哪个快

    目录 概念介绍 测试环境 开始测试 测试[单进程单线程] 测试[多进程 并行] 测试[多线程 并发] 测试[协程 + 异步] 结果对比 绘图展示 概念介绍 首先简单介绍几个概念: 进程和线程 进程就是 ...

最新文章

  1. [转] JavaScript仿淘宝智能浮动
  2. 改善代码设计 —— 总结篇(Summary)
  3. 修改maven本地仓库位置
  4. CF1082E Increasing Frequency
  5. 一年的天数 Exercise06_16
  6. 关闭 启动_Steam如何关闭开机自动启动
  7. Nacos服务注册接口
  8. MyBatis 实际使用案例-environments、environment
  9. win10电脑黑屏只有鼠标箭头_win7开机黑屏只有鼠标怎么办,我来教你解决
  10. 【HDU】2795 Billboard
  11. oracle11g 密码大小写禁用及密码有效期限制
  12. NSA漏洞预防,关闭有漏洞的端口
  13. oracle并发执行max,oracle max processes and sessions
  14. matlab改进 otsu法,otsu算法---matlab实现,和一种改进算法
  15. STM32跑马灯实验蜂鸣器实验按键输入实验NVIC中断优先级管理
  16. Python实战案例:金庸的功夫流派、人物关系的分析案例(下)
  17. python爬取微信运动_用 Python 修改微信(支付宝)运动步数,轻松 TOP1
  18. Qt安装QtCharts | 超简便方法
  19. 漫画:为什么不能打断程序员?
  20. 协调才暴力-精英乒乓论坛

热门文章

  1. 麻省理工学院(MIT)的公开课程
  2. Robert C. Martin关于UML、CASE的观点
  3. CSS-合理使用z-index控制盒子视轴高度,解决z-index失效
  4. depends用于测试程序运行所缺少的文件,可以帮我们很快找到问题
  5. 题解 luogu P2568 GCD
  6. python学习笔记(二十八)日志模块
  7. 关于Linux路由表的route命令
  8. Javascript实现信息滚动效果的方法
  9. MyBatis 事务源码分析
  10. GCPC2014 C Bounty Hunter