2

我的内核 3.0的手册页mlockall

mlockall() 锁定所有映射到调用进程地址空间的页面。这包括代码、数据和堆栈 段的页面,以及共享库、用户空间内核数据、共享内存和内存映射文件。调用成功返回时,保证所有映射的页面都驻留在 RAM 中;这些页面保证保留在 RAM 中,直到以后解锁。

后来说

使用 mlockall() 来防止页面错误延迟的实时进程应该在进入时间关键部分之前保留足够的锁定堆栈页面,以便函数调用不会导致页面错误。这可以通过调用一个函数来实现,该函数分配一个足够大的自动变量(一个数组)并写入该数组占用的内存以接触这些堆栈页面。这样,足够多的页面将被映射到堆栈并且可以锁定到 RAM 中。虚拟写入确保在临界区中甚至不会发生写时复制页面错误。

我了解此系统调用无法猜测将达到的最大堆栈大小,因此无法锁定堆栈的页面。但是为什么上面显示的 man 的第一部分说它也是为堆栈完成的?这个手册页中是否有错误,或者它只是意味着锁定是针对初始堆栈大小完成的?

4

4 回答 4

5

是的,对当前堆栈页面进行了锁定,但不是对所有可能的未来堆栈页面进行了锁定。

于 2012-04-04T19:31:31.347 回答
2

用第一句话来解释:

mlockall()锁定所有映射到调用进程地址空间的页面。

因此,如果一个页面被映射,它将被锁定。如果没有,它不会。

于 2012-04-04T19:29:22.627 回答
1

它只是在原句中提到了堆栈,因为堆栈内存与堆内存是分开映射的。堆栈没有特殊处理,如果它被映射它会被锁定,否则它不会。因此,正如您引用的第二部分所说,在您调用mlockall.

于 2012-04-04T19:35:03.110 回答
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。

于 2012-04-04T19:46:47.950 回答