22. 将文件映射到内存

本文介绍了如何使用Python的mmap模块将文件映射到内存中,以实现类似数组的随机访问。这种方法适用于访问二进制文件,如Linux的framebuffer设备文件,以及在嵌入式设备上访问内存映射的寄存器。通过映射同一文件,多个进程间还能实现通信。示例代码展示了创建1MB全0文件并映射到内存,随后在内存中写入数据和访问的过程。此方法在Linux环境下效果最佳,尤其是当以root权限运行时,能改变终端颜色布局。
摘要由CSDN通过智能技术生成

要求:

  1. 在访问某些二进制文件时,希望能把文件映射到内存中,可以像数组一样实现随机访问(例如linux的framebuffer设备文件)。

  2. 某些嵌入式设备,寄存器被编址到内存地址空间,可以映射linux的/dev/mem某范围,去访问这些寄存器。

  3. 如果多个进程同时映射同一个文件,还能实现进程通信的目的。

解决方案:

使用标准库中mmap.mmap()函数,将文件映射到进程的内存地址空间。


  • 对于mmap.mmap()函数:
mmap.mmap(fileno, length, tagname, access, offset)

从文件描述符fileno指定的文件映射长度字节,并返回一个mmap对象。如果length为0,则映射的最大长度将是调用mmap时文件的当前大小。

>>> import mmap

>>> mmap.PAGESIZE
4096

offset为起始映射的偏移量,是页对齐的,必须以mmap.PAGESIZE为单位。

  • 对于文件描述符:

内核利用文件描述符来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

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

>>> f.fileno()
3

如果使用os.open()函数也会直接返回一个文件描述符对象。


  • 方案示例:
  1. 拷贝一个1MB的全0的特殊文件为demo.bin
# dd if=/dev/zero of=demo.bin bs=1024 count=1024                #拷贝 /dev/zero 文件为 demo.bin 文件,大小为1M
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 0.00273495 s, 383 MB/s

# od -x demo.bin                #以16进制查看二进制文件
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
  1. demo.bin映射到内存中
>>> f = open('demo.bin', 'r+b')

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

>>> m
<mmap.mmap object at 0x7f74cf940978>
  1. 向内存写入数据
>>> m.write(b'abc')
3
# od -x demo.bin

0000000 6261 0063 0000 0000 0000 0000 0000 0000             #61、62、63分别是a、b、c十六进制的ASCII码
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
  1. 像数组一样访问、写入
>>> m[0]
97

>>> m[5]
0

>>> m[5] = 78
# od -x demo.bin

0000000 6261 0063 4e00 0000 0000 0000 0000 0000             #4e即是78的十六进制数
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
>>> m[8:16]
b'\x00\x00\x00\x00\x00\x00\x00\x00'

>>> m[8:16] = b'\xff' * 8               #像切片一样写入
# od -x demo.bin

0000000 6261 0063 4e00 0000 ffff ffff ffff ffff             #已经修改为ff
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000

  • 方案示例:
# ll /dev/fb0 
crw-rw---- 1 root video 29, 0 Aug 28 21:03 /dev/fb0
import mmap

f = open('/dev/fb0', 'r+b')              #linux的/dev/fb0文件即framebuffer设备文件

size = 1920 * 1080 * 4
m = mmap.mmap(f.fileno(), size)             #映射到内存中
m[:size//2] = b'\xff\xff\xff\x00' * (size // 4 // 2)                #修改内存一半的值

m.close()
f.close()

在终端模式下以root身份运行后使linux终端屏幕黑白上下各占一半。

由于我没有安装linux桌面,效果似乎不太一样,似乎全屏变白,最好是使用linux桌面测试。

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值