Python中mmap文件映射

mmap文件映射

使用內存映射的原因

爲了隨機訪問文件的內容,使用mmap將文件映射到內存中是一個高效和優雅的方法。例如,無需打開一個文件並執行大量的seek(),read(),write()調用,只需要簡單的映射文件並使用切片操作訪問數據即可。
內存映射一個文件並不會導致這個文件被讀取到內存中。也就是說,文件並沒有被複制到內存緩存或數組中。相反,操作系統僅僅爲文件內容保留了一段虛擬內存。當訪問文件的不同區域時,這些區域的內容才根據需要被讀取並映射到內存區域中。而那些從沒被訪問到的部分還是留在磁盤上。所有這些過程都是透明的,在幕後完成。

mmap介紹

mmap是一種虛擬內存映射文件的方法,它可以將一個文件或者其它對象映射到進程的地址空間,實現文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一對應關係。
*mmap 模塊提供“內存映射的文件對象”,mmap 對象可以用在使用 plain string 的地方,mmap 對象和 plain string 的區別是:

  • mmap 對象不提供字符串對象的方法;
  • mmap 對象是可變的,而 str 對象是不可變的
  • mmap 對象同時對應於打開的文件,多態於一個Python file 對象
  • mmap 對象可以切片和索引,也可以爲它的切片或索引賦值(因爲 mmap 對象是可變的),爲 mmap 對象的切片賦值時,賦值語句右值的長度必須和左值切片的長度相同。mmap 對象可以作爲進程間通過文件進行 IPC 的一種替換手段。

mmap使用細節

1、使用mmap需要注意的一個關鍵點是,mmap映射區域大小必須是物理頁大小(page_size)的整倍數(32位系統中通常是4k字節)。原因是,內存的最小粒度是頁,而進程虛擬地址空間和內存的映射也是以頁爲單位。爲了匹配內存的操作,mmap從磁盤到虛擬地址空間的映射也必須是頁。
2、內核可以跟蹤被內存映射的底層對象(文件)的大小,進程可以合法的訪問在當前文件大小以內又在內存映射區以內的那些字節。也就是說,如果文件的大小一直在擴張,只要在映射區域範圍內的數據,進程都可以合法得到,這和映射建立時文件的大小無關。具體情形參見“情形三”。
3、映射建立之後,即使文件關閉,映射依然存在。因爲映射的是磁盤的地址,不是文件本身,和文件句柄無關。同時可用於進程間通信的有效地址空間不完全受限於被映射文件的大小,因爲是按頁映射。

創建mmap對象

m=mmap.mmap(fileno, length[, flags[, prot[, access[, offset]]]])
參數 功能
fileno 文件描述符,可以是file對象的fileno()方法,或者來自os.open(),在調用mmap()之前打開文件,不再需要文件時要關閉。
length 要映射文件部分的大小(以字節爲單位),這個值爲0,則映射整個文件,如果大小大於文件當前大小,則擴展這個文件。
flags MAP_PRIVATE:這段內存映射只有本進程可用;mmap.MAP_SHARED:將內存映射和其他進程共享,所有映射了同一文件的進程,都能夠看到其中一個所做的更改;
prot mmap.PROT_READ, mmap.PROT_WRITE 和 mmap.PROT_WRITE ,mmap.PROT_READ。最後一者的含義是同時可讀可寫。
access 在mmap中有可選參數access的值有:ACCESS_READ:讀訪問。ACCESS_WRITE:寫訪問,默認。ACCESS_COPY:拷貝訪問,不會把更改寫入到文件,使用flush把更改寫到文件。

mmap對象的函數

函數 功能
close() 關閉 m 對應的文件
m.find(str, start=0) 從 start 下標開始,在 m 中從左往右尋找子串 str 最早出現的下標
m.flush([offset, n]) 把 m 中從offset開始的n個字節刷到對應的文件中
m.move(dstoff, srcoff, n) 等於 m[dstoff:dstoff+n] = m[srcoff:srcoff+n],把從 srcoff 開始的 n 個字節複製到從 dstoff 開始的n個字節,可能會覆蓋重疊的部分
m.read(n) 返回一個字符串,從 m 對應的文件中最多讀取 n 個字節,將會把 m 對應文件的位置指針向後移動
m.read_byte() 返回一個1字節長的字符串,從 m 對應的文件中讀1個字節,要是已經到了EOF還調用 read_byte(),則拋出異常 ValueError
m.readline() 返回一個字符串,從 m 對應文件的當前位置到下一個’\n’,當調用 readline() 時文件位於 EOF,則返回空字符串
m.seek(pos, how=0) 同 file 對象的 seek 操作,改變 m 對應的文件的當前位置
m.size() 返回 m 對應文件的長度(不是 m 對象的長度len(m))
m.tell() 返回 m 對應文件的當前位置
m.write(str) 把 str 寫到 m 對應文件的當前位置,如果從 m 對應文件的當前位置到 m 結尾剩餘的空間不足len(str),則拋出 ValueError
m.write_byte(byte) 把1個字節(對應一個字符)寫到 m 對應文件的當前位置,實際上 m.write_byte(ch) 等於 m.write(ch)

file的seek()函數
seek() 方法用於移動文件讀取指針到指定位置。

fileObject.seek(offset[, whence])
  • offset – 開始的偏移量,也就是代表需要移動偏移的字節數
  • whence:可選,默認值爲 0。給offset參數一個定義,表示要從哪個位置開始偏移;0代表從文件開頭開始算起,1代表從當前位置開始算起,2代表從文件末尾算起。
    如果操作成功,則返回新的文件位置,如果操作失敗,則函數返回 -1。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章