问题23:如何将文件映射到内存

问题23:如何将文件映射到内存

 

一、说明

 1)什么叫映射?

   ==>就是给一个对象(可以是变量、物理等),起一个唯一的别名,建立一一对应的关系;

 2)文件映射:将磁盘上的文件的位置,与进程逻辑地址空间中一块大小相同的区域之间的一一对应;

 3)映射后得到一个类似数组类型的东西(mmap.mmap()对象),可以通过类似操作数组的方式,达到对文件内容更改的目的;

二、优点

 1)相对于二进制文件的缺陷

  通常读写文件时,使用read()和write()方法,这两种方法都是以流的形式进行的,也就是一个字节接着一个字节的读写;如果想从某一位置开始读写,使用seek()方法调整文件指针,此方法对二进制文件的操作非常不方便,因为相对于二进制文件,数据写入文件时是以数组的形式,将数据映射到文件内,然后就以访问数组的形式访问文件,而且在对文件进行修改后,能再次通过此数组将数据同步到文件中;

 2)某些嵌入式设备,寄存器被编址到内存地址空间,我们可以映射/dev/mem某范围,取访问这些寄存器

  例如:在树莓派(为学习计算机编程教育设计的一种微型电脑)上,有一个pwm波形的发生器,若想使用此发生器,就要访问树莓派的寄存器;实际上,寄存器就是物理地址的某一特定空间;此时,如果要访问寄存器,需要将 /dev/mem 的某一范围,映射到内存中,用访问内存的方式来访问寄存器;

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

  多个进程把同一个文件映射到各自的内存空间当中,实际上它们看到的是同一个视图,也能实现进程通信的目的;

三、python中,如何做到文件映射到内存?

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

 2)格式:mmap.mmap(fileno, length[, access[, offset]]])

  #fileno:文件描述符;

   f = open('a.txt', 'w')

   f.fileno(),得到文件a.txt的描述符;

  #length:映射区域的大小,必须以(mmap.PAGSIZE)为单位;

    #页(mmap.PAGSIZE):磁盘的存储单位;

    A、0,表示全部文件;

    B、length = mmap.PAGSIZE * 8:只映射文件的前8页;

  #access:访问权限;如access = mmap.ACCESS_WRITE,表示写的权限;

  #offset:指定映射文件的某一区域,相当于文件指针

    A、指定时必须要以内存的一个页做为单位,进行文件和内存的对齐,也就是说,不能随意跳过一些字节来指定映射区域;

    B、指定的区域必须是页(mmap.PAGESIZE)的整数倍;

    C、offset = mmap.PAGSIZE * 4:表示跳过4页,从第5页开始映射;

 3)例:

复制代码
import mmap

f = open('demo.bin', 'rb')
m = mmap.mmap(f.fileno(), mmap.PAGSIZE * 8, access = mmap.ACCESS_WRITE, offset = mmap.PAGSET * 4)
#f.fileno():得到demo.bin文件的文件描述符;
#mmap.PAGSIZE * 8:映射8页;
#access = mmap.ACCESS_WRITE:以写权限对被映射的文件内容进行操作;
#offset = mmap.PAGSIZE * 4:从第5页开始对文件进行映射;
#此处的页,页就是mmap.PAGSIZE是指内存的存储单元;
#此时文件在磁盘上,并没有被Copy到内存上;

print(type(m))
#输出:mmap.mmap()

#对单个位置的字节进行更改;
m[0] = 'x88'

#切片:对一段数据进行更改;长度要和赋值的二进制字符串程度一样;
m[4:8] = 'x01'*4
复制代码

 4)其它

  A、不同的平台(也就是系统)上,mmap()函数的使用不同;

  B、文件描述符:是系统调用的open函数,在打开文件时得到的;(os.open())

  C、python中的open()函数也可以得到文件描述符:

原文地址:https://www.cnblogs.com/valorchang/p/11434483.html