本质:
将文件映射到内存,进行直接对内存进行读写(当关闭mmap时内存映射才写入到文件,中间的操作都是在内存)
优点:
1.直接读写内存,不需要任何数据拷贝。管道消息队列需要在内核和用户空间进行四次数据拷贝,而共享内存只拷贝两次数据(一次是文件到共享内存,一次是从共享内存到输出文件上)
缺点:
Windows: mmap(fileno, length[, tagname[, access[, offset]]])
Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])
参数 | 描述 |
---|---|
fileno | 文件描述符file对象的fileno()方法 |
length | 映射的长度,0表示全部映射 |
flags | |
prot | |
access | ACCESS_READ:读访问;ACCESS_WRITE:写访问,默认;ACCESS_COPY:拷贝访问,不会把更改写入到文件,使用flush把更改写到文件 |
方法 | 描述 |
---|---|
close() | 关闭映射 |
m.find(str, start=0) | 从start开始,从左到右寻找str,返回下标 |
m.flush([offset, n]) | 从offset开始的n个字节刷到对应的文件中,开启ACCESS_COPY 时使用 |
move(dstoff, srcoff, n) | 从 srcoff 开始的 n 个字节复制到从 dstoff 开始的n个字节 |
read(n) | m 对应的文件中最多读取 n 个字节,当前位置后移动 |
read_byte() | |
readline() | |
seek(pos, how=0) | 改变当前位置 |
size() | 文件的长度 |
tell() | 返回当前位置 |
write(str) | |
write_byte(byte) |
1.基本使用
import mmap#1.先创建一个文件withopen('hello.txt','wb')as f:
f.write(b"Hello Python!\n")#2.将文件与文件进行映射withopen('hello.txt','r+b')as f:
mm= mmap.mmap(f.fileno(),0)# f.fileno()文件描述符,size为0表示读取整个文件print(mm.readline())# prints "Hello Python!" # 标准读取方式print(mm[:5])# prints "Hello"# 切片读取方式
mm[6:]= b" world!\n"
mm.seek(0)# 使用seek定位光标到数据头,当前光标已到数据末(mm.tell()可获取当前光标)print(mm.readline())# prints "Hello world!"# 再次标准读取
mm.close()# 像处理文件一样关闭mmap映射
2.父子进程通信
import mmapimport osimport time
mm= mmap.mmap(-1,27)#传入文件描述符-1,使用匿名映射
mm.write(b"Original msg")# 涉及mm的读写都要记得字符串的二进制print('write successfully')
pid= os.fork()if pid==0:# 子进程中
mm.seek(0)print('Read from the mmap:')print(mm.readline())#以切片访问时,严格按照字符串长度
mm[12:]= b' sth from child'
mm.close()else:
time.sleep(2)# 用sleep使子进程先执行
mm.seek(0)print('Read from the child:')print(mm.readline())
mm.close()
3.无关进程linux的通信
import mmapimport contextlibimport timewithopen("mmap.file","w")as f:
f.write('\x00'*1024)withopen('mmap.file','r+')as f:
m= mmap.mmap(f.fileno(),1024, access=mmap.ACCESS_WRITE)for iinrange(1,10001):
m.seek(0)
m.write(b"hello")
m.flush()
time.sleep(1)
import mmapimport contextlibimport timewhileTrue:withopen('mmap.file','r')as f:with contextlib.closing(mmap.mmap(f.fileno(),1024, access=mmap.ACCESS_READ))as m:
s= m.read().replace(b'\x00',b'')print(s)
time.sleep(1)
4.无关进程win通信
server.py
import mmapimport contextlibimport timewith contextlib.closing(mmap.mmap(-1,1024, tagname='test', access=mmap.ACCESS_WRITE))as m:for iinrange(1,10001):
m.seek(0)
m.write("msg "+str(i))
m.flush()
time.sleep(1)
client.py
import mmapimport contextlibimport timewhileTrue:with contextlib.closing(mmap.mmap(-1,1024, tagname='test', access=mmap.ACCESS_READ))as m:
s= m.read(1024).replace('\x00','')print s
time.sleep(1)
参考:
https://www.xuebuyuan.com/3189076.html
https://docs.python.org/zh-cn/3.9/library/mmap.html
https://blog.csdn.net/zdy0_2004/article/details/53200250
https://blog.csdn.net/m0_37422289/article/details/79895526
https://blog.csdn.net/m0_37422289/article/details/79895526