如何将文件映射到内存?

需求:
1、在访问某些二进制文件时,希望能把文件映射到内存中去,可以实现随机访问.(framebuffer设备文件)
2、某些嵌入式设备,寄存器被编址到内存地址空间,我们可以映射/dev/mem某范围,去访问这些寄存器。
3、如果多个进程映射同一个文件,还能实现进程通信的目的

思路:
使用标准库中的mmap模块中的mmap()函数,它需要一个打开的文件描述符作为参数

测试:
1、创建一个大小为1M的二进制文件:
dd if=/dev/zero of=demo.bin bs=1024 count=1024

2、以十六进制的形式查看这个文件
od -x demo.bin

3、对这个文件进行映射

import mmap

# mmap.mmap()方法:不同的系统下该方法略有不同
# mmap(fileno, length[, tagname[, access[, offset]]]),fileno为文件描述符,length为映射区域的长度,0代表整个文件。
# 得到文件描述符
f = open('demo.bin','r+b')
fileno = f.fileno()  # 返回文件描述符:13

# 将文件映射至内存中
m = mmap.mmap(f.fileno(),0,access=mmap.ACCESS_WRITE)  # access为访问权限,这里指定为write

# 查看m的类型
print(type(m))  # mmap.mmap

# 对内存映射的对象进行相关
print(m[0]) # 0
print(m[10:20])) # 进行切片,返回:b'x00x00x00x00x00x00x00x00x00x00'
m[0] = 88  # 查看文件的内容发现已被修改 
m[4:8] = # m[4:8] = b'xff'*4  # 对切片进行修改,注意长度要对齐

# 对内存映射中的页进行相关操作
m = mmap.mmap(f.fileno(),mmap.PAGESIZE*8,access=mmap.ACCESS_WRITE,offset=mmap.PAGESIZE*4) # 映射8个页,跳过4个页,从四个页后直接进行操作
m[:0x1000] = b'xaa'* 0x1000

======================================================================

>>> import mmap

>>> mmap.mmap?
Init signature: mmap.mmap(self, /, *args, **kwargs)
Docstring:     
Windows: mmap(fileno, length[, tagname[, access[, offset]]])

Maps length bytes from the file specified by the file handle fileno,
and returns a mmap object.  If length is larger than the current size
of the file, the file is extended to contain length bytes.  If length
is 0, the maximum length of the map is the current size of the file,
except that if the file is empty Windows raises an exception (you cannot
create an empty mapping on Windows).

Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])

Maps length bytes from the file specified by the file descriptor fileno,
and returns a mmap object.  If length is 0, the maximum length of the map
will be the current size of the file when mmap is called.
flags specifies the nature of the mapping. MAP_PRIVATE creates a
private copy-on-write mapping, so changes to the contents of the mmap
object will be private to this process, and MAP_SHARED creates a mapping
that's shared with all other processes mapping the same areas of the file.
The default value is MAP_SHARED.

To map anonymous memory, pass -1 as the fileno (both versions).
File:           /usr/lib/python3.6/lib-dynload/mmap.cpython-36m-x86_64-linux-gnu.so
Type:           type
Subclasses:     

>>> import os

>>> os.open?
Signature: os.open(path, flags, mode=511, *, dir_fd=None)
Docstring:
Open a file for low level IO.  Returns a file descriptor (integer).

If dir_fd is not None, it should be a file descriptor open to a directory,
  and path should be relative; path will then be relative to that directory.
dir_fd may not be implemented on your platform.
  If it is unavailable, using it will raise a NotImplementedError.
Type:      builtin_function_or_method

>>> f = open('demo.bin','r+b')

>>> f.fileno()
12

>>> mmap.PAGESIZE
4096

>>> m = mmap.mmap(f.fileno(),0)

>>> m.write(b'abc')
3

>>> m[0]
97

>>> m[5]
0

>>> m[5] = 78

>>>  m[8:16]
b'x00x00x00x00x00x00x00x00'

>>>  m[8:16] = b'xff' * 8

>>> 1920 * 1080 *4
8294400

>>> 

=========================================

import mmap

f = open('/dev/fb0','r+b')  # fb0文件是framebuffer设备文件,fbset命令可以查看相关信息

size = 8294400
m = mmap.mmap(f.fileno(),size)

m[:size//2] = b'xffxffxffx00' * (size // 4 //2)  # 屏幕变成一半的白屏一半的黑屏

m.close()
f.close()

修改后文件的内容:

原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13303038.html