这是一篇旧文章,但是,我仍然可以在这里发表自己的想法。
从下开始,Linux首先将内存划分为页面(在x86_64系统上通常为每页面4K)。此后,创建虚拟内存,使用MMU(内存管理单元)对物理内存进行映射。
进程是从虚拟内存区域分配的内存,因此请注意,当您看到/ proc / meminfo时,您将看到VMalloc *作为虚拟内存的详细信息。
假设您有一个请求内存的进程(例如300MB-Web浏览器)。该过程将从虚拟内存中分配300MB,但是,不必将其映射到内存(即映射到物理内存)。存在用于内存管理的“写时复制”的概念,据此,如果您的进程实际上使用了从虚拟内存分配的内存(即它在内存上进行了一些写操作),则仅将其映射到物理内存。这有助于内核有效地在多进程环境中正常工作。
什么是缓存?
进程使用的大量内存是共享的。可以说,几乎所有进程都使用glibc库。当每个进程可以访问相同的内存位置并完成工作时,在内存中保留glibc的多个副本的意义何在?这种经常使用的资源被保留在高速缓存中,以便在进程需要时可以将它们引用到相同的内存位置。这有助于加快进程,因为从磁盘上一次又一次地读取glibc(etc。)会很耗时。
上面说的是共享库,文件读取也是如此。如果您是第一次读取大型文件(例如100-200MB),则将花费大量时间。但是,当您尝试再次读取相同内容时,速度会更快。数据已缓存在内存中,并且并未对所有块进行重新读取。
什么是缓冲区?
就缓冲区而言,当进程执行文件I / O时,它依靠内核的缓冲区将数据写入磁盘。进程,请求内核完成这项工作。因此,内核代表进程将数据写入其“缓冲区”,并告知进程写入已完成。内核将以异步方式继续将此缓冲区中的数据同步到磁盘。这样,进程依靠内核来选择正确的时间将数据同步到磁盘,并且进程可以继续进行下去。请记住,这是常规进程正在执行的常规I / O。但是,需要确认磁盘上实际完成I / O的专用过程可以使用其他机制在磁盘上进行I / O。一些开源实用程序是libaio。此外,还有一些方法可以调用显式同步到在流程上下文中打开的FD,
那是什么页面错误?
考虑一个示例,当您启动一个进程(例如Web浏览器)时,其二进制文件约为300MB。但是,完整的300MB Web浏览器二进制文件无法立即开始工作。该过程在其代码中不断地从功能转移到功能。如前所述,虚拟内存将消耗300MB,但并非所有内存都映射到物理内存(RSS-常驻内存会更少,请参见顶部输出)。当代码执行到达某个点时,实际上并没有实际映射内存,就会出现页面错误。内核会将内存映射为物理内存,并将内存页面与您的进程相关联。这种页面错误称为“次要页面错误”。类似地,当进程正在执行文件I / O时,会引发主要页面错误。
何时以及为何发生掉期交易?
情况一:
与上面的细节一致,让我们考虑一种情况,当大量内存成为内存映射时。现在,启动了一个进程,该进程需要内存。如上所述,内核将执行一些内存映射。但是,没有足够的物理RAM来映射内存。现在,内核将首先查看缓存,它将具有一些未使用的旧内存页面。它将这些页面刷新到一个单独的分区(称为SWAP)上,释放一些页面,并将释放的页面映射到即将到来的新请求。由于磁盘写入要比固态RAM慢得多,因此此过程要花费大量时间,因此可以看到速度变慢。
情况2:
假设您看到系统中有很多可用内存。即使那样,您仍然看到有很多交换发生。可能存在内存碎片的问题。考虑一个进程,该进程需要内核提供50MB的连续内存。(请牢记相邻)。显然,内核会随机地将页面分配给不同的进程,并释放其中的一些进程。但是,当我们需要连续的内存时,它将不得不寻找能够满足流程需求的块。如果无法获得此类内存,则必须换出一些旧的内存页面,然后分配连续的页面。即使在这种情况下,也会发生掉期。从2.6或更高版本的内核开始,此类碎片问题已大大减少。但是,如果系统长时间运行,则可能仍然会出现此类问题。
请参见此示例(vmstat输出)
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 2016-10-30 03:57:04,我们看到仍然有大量的可用RAM。但是,即使这样换出还是发生了。在这一点上,我们检查了进程树,但没有看到需要占用如此大量内存(比可用内存更多)的进程。明显的怀疑是上述情况2。我们在上面检查了buddyinfo和zoneinfo日志(使用echo m> / proc / sysrq-trigger进行检查,输出进入syslogs)。
对于我们的普通系统,区域信息的比较是这样的。并且下面还提到了缓存/空闲/低内存的图表
查看信息,很显然在节点0和节点1正常中存在内存碎片(节点是基于NUMA的计算机,因此有多个节点(请参阅numactl以检查系统信息))。
内存碎片也是即使在有可用内存的情况下交换使用量仍会增加的原因。