要求:

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

解决方案:

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

          • -
  • 对于mmap.mmap()函数:
<pre class="brush:html;toolbar:false">mmap.mmap(fileno, length, tagname, access, offset)

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


<pre class="brush:html;toolbar:false">>>> import mmap>>> mmap.PAGESIZE4096

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

  • 对于文件描述符:

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

<pre class="brush:html;toolbar:false">>>> f = open('demo.bin', 'r+b')>>> f.fileno()3

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

          • -
  • 方案示例:
  1. 拷贝一个1MB的全0的特殊文件为demo.bin
<pre class="brush:html;toolbar:false"># dd if=/dev/zero of=demo.bin bs=1024 count=1024                #拷贝 /dev/zero 文件为 demo.bin 文件,大小为1M1024+0 records in1024+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映射到内存中
<pre class="brush:html;toolbar:false">>>> f = open('demo.bin', 'r+b')>>> f.fileno()3>>> m = mmap.mmap(f.fileno(), 0)>>> m<mmap.mmap object at 0x7f74cf940978>
  1. 向内存写入数据
<pre class="brush:html;toolbar:false">>>> m.write(b'abc')3
<pre class="brush:html;toolbar:false"># od -x demo.bin0000000 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. 像数组一样访问、写入
<pre class="brush:html;toolbar:false">>>> m[0]97>>> m[5]0>>> m[5] = 78
<pre class="brush:html;toolbar:false"># od -x demo.bin0000000 6261 0063 4e00 0000 0000 0000 0000 0000             #4e即是78的十六进制数0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
<pre class="brush:html;toolbar:false">>>> m[8:16]b'\x00\x00\x00\x00\x00\x00\x00\x00'>>> m[8:16] = b'\xff' * 8               #像切片一样写入
<pre class="brush:html;toolbar:false"># od -x demo.bin0000000 6261 0063 4e00 0000 ffff ffff ffff ffff             #已经修改为ff0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
          • -
  • 方案示例:
<pre class="brush:html;toolbar:false"># ll /dev/fb0 crw-rw---- 1 root video 29, 0 Aug 28 21:03 /dev/fb0
<pre class="brush:html;toolbar:false">import mmap

f = open('/dev/fb0', 'r+b')              #linux的/dev/fb0文件即framebuffer设备文件size = 1920 * 1080 * 4m = mmap.mmap(f.fileno(), size)             #映射到内存中m[:size//2] = b'\xff\xff\xff\x00' * (size // 4 // 2)                #修改内存一半的值m.close()f.close()

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

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

在这里插入图片描述

          • -

标签: 内存, 文件, 映射, demo, mmap, x00

相关文章推荐

添加新评论,含*的栏目为必填