mlock() - Unix,Linux系統呼叫 - 技術教學
Tutorials Point


  Unix入門
  Unix Shell程式設計
  高階Unix
  Unix有用參考
  Unix有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  首頁     參考資料     討論論壇     關於TP  

mlock() - Unix,Linux系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

mlock、munlock、mlockall、munlockall - 鎖定和解鎖記憶體

概要

#include <sys/mman.h> 

int mlock(const void *addr, size_t len);

int munlock(const void *addr, size_t len);

int mlockall(int flags);

int munlockall(void);

描述

mlock() 和 mlockall() 分別將呼叫程序的虛擬地址空間的部分或全部鎖定到 RAM 中,防止該記憶體被分頁到交換區。munlock() 和 munlockall() 執行相反的操作,分別解鎖呼叫程序的虛擬地址空間的部分或全部,以便核心記憶體管理器在需要時可以再次將指定虛擬地址範圍內的頁面交換出去。記憶體鎖定和解鎖以整個頁面的單位執行。

mlock() 和 munlock()

mlock() 鎖定從addr開始,持續len位元組的地址範圍內的頁面。當呼叫成功返回時,包含指定地址範圍一部分的所有頁面都保證駐留在 RAM 中;這些頁面保證會留在 RAM 中,直到以後解鎖。

munlock() 解鎖從addr開始,持續len位元組的地址範圍內的頁面。此呼叫之後,核心可以再次將包含指定記憶體範圍一部分的所有頁面移動到外部交換空間。

mlockall() 和 munlockall()

mlockall() 鎖定對映到呼叫程序地址空間中的所有頁面。這包括程式碼、資料和堆疊段的頁面,以及共享庫、使用者空間核心資料、共享記憶體和記憶體對映檔案。當呼叫成功返回時,所有對映的頁面都保證駐留在 RAM 中;這些頁面保證會留在 RAM 中,直到以後解鎖。

flags引數透過一個或多個以下常量的按位或運算來構造

標籤描述
MCL_CURRENT 鎖定當前對映到程序地址空間中的所有頁面。
MCL_FUTURE 鎖定將來將對映到程序地址空間中的所有頁面。例如,這些可能是不斷增長的堆和堆疊所需的新頁面,以及新的記憶體對映檔案或共享記憶體區域。
如果指定了MCL_FUTURE,則以後的系統呼叫(例如,mmap(2)、sbrk(2)、malloc(3))可能會失敗,如果它會導致鎖定的位元組數超過允許的最大值(見下文)。在相同情況下,堆疊增長也可能失敗:核心將拒絕堆疊擴充套件並向程序傳送SIGSEGV訊號。

munlockall() 解鎖對映到呼叫程序地址空間中的所有頁面。

備註

記憶體鎖定有兩個主要應用:即時演算法和高安全資料處理。即時應用程式需要確定性計時,並且與排程一樣,分頁是導致程式執行意外延遲的主要原因之一。即時應用程式通常還會切換到具有sched_setscheduler(2)的即時排程程式。加密安全軟體通常將關鍵位元組(如密碼或金鑰)處理為資料結構。由於分頁,這些秘密可能被轉移到永續性交換儲存介質上,在那裡它們可能在安全軟體已擦除 RAM 中的秘密並終止後很長時間內被敵人訪問。(但請注意,無論記憶體鎖定如何,筆記型電腦和某些臺式電腦上的掛起模式都會將系統 RAM 的副本儲存到磁碟上。)

正在使用mlockall() 來防止頁面錯誤延遲的即時程序應該在進入時間關鍵部分之前預留足夠的已鎖定堆疊頁面,以便函式呼叫不會導致頁面錯誤。這可以透過呼叫分配足夠大的自動變數(陣列)並寫入該陣列佔用的記憶體以訪問這些堆疊頁面來實現。這樣,將為堆疊對映足夠的頁面,並可以將其鎖定到 RAM 中。虛擬寫入確保即使在關鍵部分也不會發生寫時複製頁面錯誤。

記憶體鎖不會被透過fork(2)建立的子程序繼承,並且會在execve(2)期間或程序終止時自動刪除(解鎖)。

如果透過munmap(2)取消對映地址範圍,則該地址範圍上的記憶體鎖將自動刪除。

記憶體鎖不會堆疊,即,透過呼叫mlock() 或mlockall() 多次鎖定的頁面將透過對相應範圍的單個munlock() 呼叫或透過munlockall() 來解鎖。只要至少在一個位置或至少一個程序中鎖定,對映到多個位置或多個程序的頁面就會保持鎖定在 RAM 中。

Linux備註

在 Linux 下,mlock() 和munlock() 會自動將addr向下舍入到最接近的頁面邊界。但是,POSIX.1-2001允許實現要求addr與頁面對齊,因此可移植應用程式應確保這一點。

限制和許可權

在 Linux 2.6.8 及更早版本中,程序必須具有特權(CAP_IPC_LOCK)才能鎖定記憶體,並且RLIMIT_MEMLOCK軟資源限制定義了程序可以鎖定的記憶體量限制。

從 Linux 2.6.9 開始,對特權程序可以鎖定的記憶體量沒有限制,而RLIMIT_MEMLOCK軟資源限制改為定義非特權程序可以鎖定的記憶體量限制。

返回值

成功時,這些系統呼叫返回 0。發生錯誤時,返回 -1,errno 設定為適當的值,並且不會更改程序地址空間中的任何鎖。

錯誤

標籤描述
ENOMEM (Linux 2.6.9 及更高版本) 呼叫者具有非零RLIMIT_MEMLOCK軟資源限制,但嘗試鎖定的記憶體超過允許的限制。如果程序具有特權(CAP_IPC_LOCK),則不會強制執行此限制。
ENOMEM (Linux 2.4 及更早版本) 呼叫程序嘗試鎖定的記憶體超過 RAM 的一半。
EPERM (Linux 2.6.9 及更高版本) 呼叫者沒有特權(CAP_IPC_LOCK)並且其RLIMIT_MEMLOCK軟資源限制為 0。
EPERM (Linux 2.6.8 及更早版本) 呼叫程序沒有足夠的許可權來呼叫munlockall()。在 Linux 下,需要CAP_IPC_LOCK功能。
對於mlock() 和munlock()
EINVAL len為負。
EINVAL (不在 Linux 上) addr不是頁面大小的倍數。
ENOMEM 指定地址範圍的某些部分不對應於程序地址空間中對映的頁面。
對於mlockall()
EINVAL 指定了未知的flags
對於munlockall()
EPERM (Linux 2.6.8 及更早版本) 呼叫者沒有特權(CAP_IPC_LOCK)。

缺陷

在 2.4 系列 Linux 核心(包括 2.4.17)中,一個缺陷導致mlockall() MCL_FUTURE標誌在fork(2) 中繼承。這在核心 2.4.18 中得到糾正。

從核心 2.6.9 開始,如果特權程序呼叫mlockall(MCL_FUTURE),然後降低特權(例如,透過將其有效 UID 設定為非零值來丟失CAP_IPC_LOCK功能),則如果遇到RLIMIT_MEMLOCK資源限制,則以後的記憶體分配(例如,mmap(2)、brk(2))將失敗。

可用性

在可使用mlock() 和munlock() 的 POSIX 系統上,_POSIX_MEMLOCK_RANGE在 <unistd.h> 中定義,並且頁面中的位元組數可以透過 <limits.h> 中的常量PAGESIZE(如果已定義)或透過呼叫sysconf(_SC_PAGESIZE)來確定。

在可使用mlockall() 和munlockall() 的 POSIX 系統上,_POSIX_MEMLOCK在 <unistd.h> 中定義為大於 0 的值。(另見sysconf(3))。

符合標準

POSIX.1-2001, SVr4

另請參見



previous next Printer Friendly

廣告


  

廣告



廣告
© . All rights reserved.