歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 內存映射mmap

內存映射mmap

日期:2017/3/1 9:08:52   编辑:Linux編程

Table of Contents

  • 1. 什麼是mmap
  • 2. 使用方法
    • 2.1. mmap構造器的格式
    • 2.2. 例子1
    • 2.3. 例子2
  • 3. 其它
  • 4. 參考資料

什麼是mmap

通常在Unix系統裡有兩種操作的數據類型:內存地址和流文件(stream)。通過操作內存地址的方法涉及的操作有:pointers, malloc/free之類,而操作流文件涉及的方法有read/write/seek等系統調用或者send/recv/etc等socket操作。而mmap提供了結合上述兩種類型的操作方式。簡單來講,mmap可以創建一個內存映射(memory-mapped)類型的文件,可以直接在內存操作文件,而不需要使用通常的read,wirte這些系統I/O調用。這樣的好處是避免了操作文件是頻繁地系統調用。

使用方法

內存映射(memory-mapped)可以像字符串和文件對象一樣操作,通過 mmap 來創建。
例子中采用的hello.txt文件如下:

Hello, i am Nisen,
Nice to meet you!
Goodbye.

mmap構造器的格式

# Unix version
class mmap.mmap(fileno, length[, flags[, prot[, access[, offset]]]])

# Windows version
class mmap.mmap(fileno, length[, tagname[, access[, offset]]])

fileno是流文件的描述符,length指定映射文件到內存的bytes的長度,設置為0的話代表全部。Unix接口中的flags指定這個創建出來的mapping是否對創建的進程私有,默認是共享的。prot和access指定需要的內存保護(讀寫相關),其它參數的含義可以參照文檔。
接下來讓我們采用Unix的接口,做些實驗吧。

例子1

import mmap

with open('hello.txt', 'r') as f:
    m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    print m.readline()
    m.close()

運行的結果如下:

Hello, i am Nisen,

python3.2以後mmap支持用with的方式操作

# New in version 3.2: Context manager support.
with open('hello.txt', 'r') as f:
    with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:
        print('First 10 bytes via read :', m.read(10))
        print('First 10 bytes via slice:', m[:10])

運行後的結果

python3 test.py
First 10 bytes via read : b'Hello, i am Nisen,\nNice to meet you!\nGoodbye.\n'
First 10 bytes via slice: b'Hello, i a'

例子2

常見的方法如下

with open('hello.txt', 'r+') as f:
    # 指定訪問權限為write, 一共有3種權限指定:ACCESS_READ, ACCESS_WRITE, ACCESS_COPY
    m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_WRITE)

    # 輸出一行
    print m.readline()

    # 指針重置
    m.seek(0)

    # 查找"Nisen"出現的第一個地方,返回索引
    index = m.find('Nisen')
    print index

    m.seek(0)

    # 直接修改內容
    m[index: index+5] = "Rubby"

    # 將內存中的修改存到磁盤中的文件上
    m.flush()

    m.seek(0)
    print m.readline()

    # 關閉內存映射文件
    m.close()

運行結果如下:

➜ python test2.py
Hello, i am Nisen,

12
Hello, i am Rubby,

其它

  1. mmap的read()方法在python3.3開始可以接受空參數,表示讀取文件所有的內容
  2. 在創建mmap對象指定權限的時候,注意本來文件描述符擁有的權限。如果使用open()打開文件的權限指定了'r', 用mmap創建映射對象時指定 ACCESS_WRITE ,那麼會報 Permission denied 的錯誤
  3. 關於文件打開模式"r+"和"w+"的用法可以參考這裡這裡
  4. 在多線程編程時,如果多個線程以只讀的方式訪問同一個文件,那麼可以采用mmap創一個映射對象來減少內存的使用提升性能
  5. mmap會將文件對象一次讀取到連續內存空間上,如果文件過大導致找不到可用的內存空間,那麼創建這個映射對象將會失敗
  6. mmap加快文件操作的例子可以參照這裡

參考資料

  • https://docs.python.org/2.7/library/mmap.html
  • https://docs.python.org/3.5/library/mmap.html
  • https://pymotw.com/3/mmap/
  • http://pythoncentral.io/memory-mapped-mmap-file-support-in-python/
  • http://stackoverflow.com/questions/21113919/difference-between-r-and-w-in-fopen
  • https://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/

Copyright © Linux教程網 All Rights Reserved