首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

[linux][memory]mlock技术分析和使用以及问题

前言: 使用了mlock,会把内存lock在内存中,不会被交换,在一定场景下,可以提高性能。 虚拟化场景下,qemu也可以选择lock住一部分内存,来提高Guest的性能。 下文来分析一下mlock的原理,以及可能会遇到的问题。 分析: 1,mlock 代码:linux-4.0.4/mm/mlock.c中,实现了mlock/munlock/mlockall/munlockall系统调用:

先判断是否可以can_do_mlock(判断rlimit的memlock选项,即可以通过ulimit -l来修改),再执行do_mlock(给指定的地址范围内的vma加上VM_LOCKED标记,这里需要注意一下,因为vma的标记位发生了变化,那么就可能会导致vma的分片或者合并),最后再执行__mm_populate。 2,__mm_populate

这个函数的主要逻辑,就是找到指定的地址范围内的所有vma,并把它们分配页面了。逻辑在《[linux][memory]进程的最大内存使用量的讨论》文中也有提到。 另外,这里需要注意一点,在执行这段函数的过程中,是需要使用信号量mm->mmap_sem的。如果这里需要处理的地址空间比较大,那么就意味着mm->mmap_sem被占用的时间会比较长。 3,smaps 在用户态,观察某进程到底有多少内存被lock住了,可以通过:cat /proc/PID/smaps查看。其中VmFlags的lo标记就是。另外,可以通过查看size和rss看到vma的大小和物理内存的大小。

4,mlock对于qemu的好处 综上,mlock带来的好处有几个方面: a,通过__mm_populate预先分配好内存,可以减少运行时的page fault的次数。 b,禁用swap,防止内存被交换。 这几点对于qemu尤其重要,qemu不仅仅是Host上的一个用户进程,其中更是运行着Guest。跑在VM mode下的CPU,触发了page fault的处理过程比普通进程发生缺页的处理过程要复杂,而且代价更大。 5,mlock导致的Guest启动变慢 针对上述的mlock对于qemu的好处,那么可以在qemu启动的时候,对Guest分配的内存执行mlock。 在2节中提到,对大块的vma执行了__mm_populate,可能需要比较长的时间。作者这里有一个经验值,在一个用足够大的空闲内存的情况下,对32G内存执行mlock,大约需要10S左右的时间(具体的执行时间当然和CPU型号有关,这里只是一个经验值)。 所以,不能在启动时同步执行这个mlock,否则Guest启动慢了10S是一个比较尴尬的情况。所以,可以选择使用多线程,用一个线程,后台执行就行了吧。 然而,新的问题又来了。会发现主线程的执行依然很慢,还需要这10S。 在2节中提到mm->mmap_sem被__mm_populate长时间占用。 再继续分析linux-4.0.4/arch/x86/mm/fault.c: 分析__do_page_fault(进程发生page fault的时候,处理的handler)函数会发现,这里也需要使用mm->mmap_sem。 所以,在qemu启动的早期阶段,会较多次数发生page fault(这个完全是正常的,比如说,malloc了一段内存,如果这段内存所在的page第一次被访问到,就会发生page fault)。而此时,mlock也在执行,就发生了抢占sem的情况。 尽管我们尽量在用户态尝试并发执行两段逻辑,但是,不巧的是,在kernel中访问了临界资源,被迫串行。所以,尽量保证qemu控制逻辑的代码先完整执行,再对Guest的性能优化。解决方案也就出来了:在qemu将要进入main loop之前,再唤醒另外一个线程,执行mlock。 后记: mlock在绝大多数情况下,都可以很好的工作,参数不多,用法也很简单。 但是,在这种比较偶然少见的情况下,需要了解mlock的原理才能进一步优化,得出更好的结果。 “只要会用就行,不需要关注它是怎么实现的。”这句话,在这种情况,是不是比较可笑?

下一篇
举报
领券