2012-04-04 55 views
2

mlockall手冊頁上我的內核3.0說你如何理解mlockall手冊頁?

mlockall用於()鎖映射到 調用進程的地址空間中所有頁面。這包括代碼頁,數據和堆棧 段以及共享庫,用戶空間內核數據,共享內存和內存映射文件 。當呼叫成功返回時,所有映射的頁面保證 駐留在RAM中;頁面 保證留在RAM中,直到稍後解鎖。

後來說,使用mlockall用於(),以防止對 頁面故障延遲

實時進程進入 時間關鍵部分之前應該預留足夠的鎖定堆棧頁,這樣就沒有調用 函數 可能導致頁面錯誤。這可以通過調用一個分配足夠大的自動變量(一個數組)的函數來實現,並且寫入該數組佔用的內存以觸及這些堆棧頁。這樣, 足夠的頁面將被映射爲堆棧並且可以被鎖定到RAM中。虛擬寫入確保甚至在臨界區域中甚至不會發生寫入時複製頁面錯誤。

我知道這個系統調用無法猜測將會達到的最大堆棧大小,因此無法鎖定堆棧的頁面。但爲什麼上面顯示的男人的第一部分說,這也是爲堆棧完成的?這個手冊頁是否有錯誤,還是僅僅意味着鎖定是爲初始堆棧大小完成的?

回答

3

是的,鎖定是爲當前堆棧頁面完成的,但不適用於所有可能的堆棧頁面。

+0

請注意,Linux最初爲每個進程提交128k的堆棧空間,似乎沒有辦法調整/覆蓋它。因此,'mlockall'將鎖定至少128k,這比任何合理的程序都需要更多。 – 2012-04-05 00:56:00

2

它由第一句話解釋:

mlockall()鎖定所有頁面映射到調用進程的地址空間。

所以如果一個頁面被映射,它將被鎖定。如果沒有,它不會。

1

它只是在原始語句中提到堆棧,因爲堆棧內存與堆內存分開映射。對堆棧沒有特別的處理,如果它被映射,它將被鎖定,否則它不會。因此,如您引用的第二部分所述,在您撥打mlockall之前,將堆棧增大到您的代碼運行時將達到的最大大小非常重要。

1

其實,從mm/mlock.c源代碼的快速閱讀中,我會說它只是鎖定的一切:所有當前映射的頁面。

static int do_mlockall(int flags) 
{ 
     struct vm_area_struct * vma, * prev = NULL; 
     unsigned int def_flags = 0; 

     if (flags & MCL_FUTURE) 
       def_flags = VM_LOCKED; 
     current->mm->def_flags = def_flags; 
     if (flags == MCL_FUTURE) 
       goto out; 

     for (vma = current->mm->mmap; vma ; vma = prev->vm_next) { 
       vm_flags_t newflags; 

       newflags = vma->vm_flags | VM_LOCKED; 
       if (!(flags & MCL_CURRENT)) 
         newflags &= ~VM_LOCKED; 

       /* Ignore errors */ 
       mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags); 
     } 
out: 
     return 0; 
} 

儘管larsmans說,我也認爲它也適用於所有未來的頁面,如果MCL_FUTURE也被指定。 在這種情況下,current-> mm-> def_flags被更新爲包含VM_LOCKED。

+0

問題是,如果指定了'MCL_FUTURE',它將在發生錯誤時將鎖定在將來的頁面中。但是它無法預測將來哪些頁面將被訪問並現在鎖定它們。所以,如果你想避免未來的硬頁面錯誤,你必須確保在你調用'mlockall'時頁面被映射。否則,每個頁面在駐留時都會發生一次故障。 – 2012-04-07 04:05:57