2012-04-04 100 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