Linux内存文件节点/proc/sys/vm

作者 by adtxl / 2022-03-07 / 暂无评论 / 528 个足迹

转载自https://blog.csdn.net/cassie_huang/article/details/80633328

这些参数主要是用来调整virtual memory子系统的行为以及数据的写出(从RAM到ROM)。
这些节点(参数)的默认值和初始化的过程大部分都可以在mm/swap.c中找到。

1. vm目录中的文件节点

以某平台为例,

console:/proc/sys/vm # ls -al
total 0
dr-xr-xr-x 1 root root 0 2022-03-07 09:10 .
dr-xr-xr-x 1 root root 0 1970-01-01 00:00 ..
-rw-r--r-- 1 root root 0 2022-03-07 09:10 admin_reserve_kbytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 block_dump
--w------- 1 root root 0 2022-03-07 09:10 compact_memory
-rw-r--r-- 1 root root 0 2022-03-07 09:10 compact_unevictable_allowed
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_background_bytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_background_ratio
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_bytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_expire_centisecs
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_ratio
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirty_writeback_centisecs
-rw-r--r-- 1 root root 0 2022-03-07 09:10 dirtytime_expire_seconds
--w------- 1 root root 0 2022-03-07 09:10 drop_caches
-rw-r--r-- 1 root root 0 2022-03-07 09:10 extfrag_threshold
-rw-r--r-- 1 root root 0 2022-03-07 09:10 extra_free_kbytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 hugetlb_shm_group
-rw-r--r-- 1 root root 0 2022-03-07 09:10 laptop_mode
-rw-r--r-- 1 root root 0 2022-03-07 09:10 legacy_va_layout
-rw-r--r-- 1 root root 0 2022-03-07 09:10 lowmem_reserve_ratio
-rw-r--r-- 1 root root 0 2022-03-07 09:10 max_map_count
-rw-r--r-- 1 root root 0 2022-03-07 09:10 memory_failure_early_kill
-rw-r--r-- 1 root root 0 2022-03-07 09:10 memory_failure_recovery
-rw-r--r-- 1 root root 0 2022-03-07 09:10 min_free_kbytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 mmap_min_addr
-rw------- 1 root root 0 2022-03-07 09:10 mmap_rnd_bits
-rw------- 1 root root 0 2022-03-07 09:10 mmap_rnd_compat_bits
-rw-r--r-- 1 root root 0 2022-03-07 09:10 nr_hugepages
-rw-r--r-- 1 root root 0 2022-03-07 09:10 nr_overcommit_hugepages
-rw-r--r-- 1 root root 0 2022-03-07 09:10 oom_dump_tasks
-rw-r--r-- 1 root root 0 2022-03-07 09:10 oom_kill_allocating_task
-rw-r--r-- 1 root root 0 2022-03-07 09:10 overcommit_kbytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 overcommit_memory
-rw-r--r-- 1 root root 0 2022-03-07 09:10 overcommit_ratio
-rw-r--r-- 1 root root 0 2022-03-07 09:10 page-cluster
-rw-r--r-- 1 root root 0 2022-03-07 09:10 panic_on_oom
-rw-r--r-- 1 root root 0 2022-03-07 09:10 percpu_pagelist_fraction
-rw-r--r-- 1 root root 0 2022-03-07 09:10 stat_interval
-rw------- 1 root root 0 2022-03-07 09:10 stat_refresh
-rw-r--r-- 1 root root 0 2022-03-07 09:10 swappiness
-rw-r--r-- 1 root root 0 2022-03-07 09:10 user_reserve_kbytes
-rw-r--r-- 1 root root 0 2022-03-07 09:10 vfs_cache_pressure
-rw-r--r-- 1 root root 0 2022-03-07 09:10 watermark_scale_factor

2. 节点含义

  • admin_reserve_kbytes

系统中为拥有cap_sys_admin的权限(可以大致理解到root权限)的user预留的free memory数量
admin_reserve_kbytes 默认为min(3% of free pages, 8MB)(也就是3%的free pages与8MB中较小的值)
在必要的情况下,在默认的大量使用的'guess' 模式下,能有足够多的memory给管理员登录和杀死进程。
运行在大量使用‘never’下的系统应该增加这个值到用于恢复的程序的完整虚拟内存大小。否则,root无法登录来恢复系统。

如何计算一个可用的预留最小值呢?

sshd or login + bash (or some other shell) + top (or ps, kill, etc.) (需要考虑到这几个程序需要的虚拟内存)
对于大量使用'guess'模式,我们可以算RSS。在x86_64,这个值是8MB。

对于大量使用'never'模式,我们可以采用他们的虚拟大小的最大值再加上他们的RSS。(VSZ+RSS)。在x86_64 这个值是128MB.

改变这个值,每当程序需要内存时都会收到影响。

  • block_dump

把block_dump设置为一个非零值,可以打开block I/O调试。在Documentation/laptops/laptop-mode.txt可以查看更多关于block I/O调试的内容。

  • compact_memory

在CONFIG_COMPACTION设置了的时候这个参数才能访问。这个参数被写1的时候,所有的zone会被压缩,因此所有可用的memory都是连续的块。对于需要大量内存的情况,这很重要,尽管进程可以根据需要直接压缩内存。

  • compact_unevictable_allowed

在CONFIG_COMPACTION设置了的时候这个参数才能访问。这个参数被写1的之后,压缩是可以检查不能被写出的、lru(最近最少使用)的页面以便进行压缩的。这个应该使用在为了大的连续内存而可以接受小的页面错误的系统中。这个参数被设置为0来阻止不能被写出的页面的移动。默认值是1。

  • dirty_background_bytes

这个值包含后台内核刷新进程即将开始回写到的内存的大小。
Contains the amount of dirty memory at which the background kernel flusher threads will start writeback.
Note:dirty_background_bytesdirty_background_ratio互斥使用。一次只能指定他们中的一个。当其中一个sysctl 被写入,那会立马在dirty memory的范围的计算过程中起作用,并且另外一个的值读出来是0。

  • dirty_background_ratio

后台内核刷新线程即将写出的脏数据所占的页面,占包括free页面和可回收页面的在内的总可用页面数的百分比。这里说的总可用内存不等于系统的总内存。

  • dirty_bytes

一个生成磁盘的进程写入的"memory dirty"的大小,并且这个"memory dirty"会自动回写。
注:dirty_bytes 和dirty_ratio的使用相关。一次只能指定他们中的一个。当一个sysctl被调用,那它会立马被用来评估“dirty memory”的极限并且其他的sysctl读出来的结果是0。
注:dirty_bytes 被允许的最小值是两页(字节数);任何比这个小的值的设定都会被忽略,并且保持原来的值。

  • dirty_expire_centisecs

这个可调的值是用来定义脏数据因为足够老而被内核清理线程(kernel flusher threads)写出的时间。

它的单位是百分之一秒。在“dirty in-memory”中存在时间超过这个值的数据会在下一次清理进程醒过来的时候写出。

  • dirty_ratio

这个参数, 是指free pages和reclaimable pages占总内存的一个百分比,当达到这个百分比的时候,生成磁盘写操作的进程将会自动开始把脏数据写出。
总可用memory和总系统内存不相等。

  • dirty_writeback_centisecs

内核清理线程将定期地醒过来,并且讲脏数据写出到磁盘。这个参数就是指这个时间间隔,单位是百分之一秒。
把这个值设置为0就完全地disable了定期回写的做法。

  • dirtytime_expire_seconds

  • drop_caches

对这个参数写入,会导致内核清扫caches以及像inodes之类的可回收的slab对象。一旦清理了,他们的内存就变成可用的了。

清理cache:
echo 1 > /proc/sys/vm/drop_caches
清理可回收的slab对象(包括目录和inodes):
echo 2 > /proc/sys/vm/drop_caches
清理cache和可回收的slab对象:
echo 3 > /proc/sys/vm/drop_caches
这个操作非破坏性的,不会清理脏对象。要增加这个操作可清理的对象的数量,可以运行“sync”后再往/proc/sys/vm/drop_caches节点写值。这样会使得系统的脏对象变得最少,并且增加可以被清理的对象。

这个文件不是一种用来控制各种内核cache(inodes,目录,cache等)增长的手段。这些对象会在系统别的地方需要内存时被内核主动回收。

使用这个文件会造成一些性能问题。因为这个操作舍弃了缓存的一些对象,而可能需要大量的I/O和CPU来重新创建这些被舍弃的对象,特别是当他们被大量使用的时候。因此,在测试和debug之外的环境中,是不建议使用的。

当这个文件被使用的时候,你可能可以看到kernel log中有这样的信息:
cat (1234): drop_caches: 3

这只是个提醒。这并不代表你的系统有任何问题。要disable这个功能,echo 4 (bit 3)到drop_caches

  • extfrag_threshold

这个参数影响的是内核要在为了满足一个高阶(high-order )的内存需求时,是压缩内存还是直接回收。
在debugfs下面的extfrag/extfrag_index文件显示的是系统中每个zone中的每一个order的碎片编号是什么。
值趋于0意味着内存分配会因为内存不足而失败,值是1000是指分配失败是因为碎片,值是-1则指主要水位满足,就能分配成功。
如果碎片index 小于等于extfrag_threshold,那么内核不会压缩一个zone里面的内存。
这个值的默认值是500。

  • extra_free_kbytes

这个参数告诉VM在后台回收程序开始工作的门限值和直接回收(内存分配进程做的)的门限值之间保持额外的free memory。
需要低延迟的内存分配和在内存分配具有突发性的之后很有用,例如一个实时应用,接受和发送最大的信息可能达到200MB的网络数据(导致内核内存分配),这就需要200MB的额外的可用内存来避免直接回收内存相关的延迟。

  • hugetlb_shm_group

hugetlb_shm_group中包含了被允许使用hugetlb页来创建SysV共享内存段的group id

  • laptop_mode

laptop_mode 是一个用来控制"laptop mode"的开关。这个开关控制的所有先关的东西都会在Documentation/laptops/laptop-mode.txt中讨论。

  • legacy_va_layout

如果这个值是一个非0值,这就disable了新的32位的内存映射结构-内核会对所有进程使用legacy (2.4)结构。

  • lowmem_reserve_ratio

For some specialised workloads on highmem machines it is dangerous for
the kernel to allow process memory to be allocated from the "lowmem"
zone. This is because that memory could then be pinned via the mlock()
system call, or by unavailability of swapspace.

And on large highmem machines this lack of reclaimable lowmem memory
can be fatal.

So the Linux page allocator has a mechanism which prevents allocations
which _could_ use highmem from using too much lowmem. This means that
a certain amount of lowmem is defended from the possibility of being
captured into pinned user memory.

(The same argument applies to the old 16 megabyte ISA DMA region. This
mechanism will also defend that region from allocations which could use
highmem or lowmem).

The lowmem_reserve_ratio tunable determines how aggressive the kernel is
in defending these lower zones.

If you have a machine which uses highmem or ISA DMA and your
applications are using mlock(), or if you are running with no swap then
you probably should change the lowmem_reserve_ratio setting.

The lowmem_reserve_ratio is an array. You can see them by reading this file.

% cat /proc/sys/vm/lowmem_reserve_ratio
256     256     32

Note: # of this elements is one fewer than number of zones. Because the highest zone's value is not necessary for following calculation.

But, these values are not used directly. The kernel calculates # of protection
pages for each zones from them. These are shown as array of protection pages
in /proc/zoneinfo like followings. (This is an example of x86-64 box).
Each zone has an array of protection pages like this.

Node 0, zone      DMA
  pages free     1355
        min      3
        low      3
        high     4
 :
 :
    numa_other   0
        protection: (0, 2004, 2004, 2004)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  pagesets
    cpu: 0 pcp: 0
        :

These protections are added to score to judge whether this zone should be used
for page allocation or should be reclaimed.

In this example, if normal pages (index=2) are required to this DMA zone and
watermark[WMARK_HIGH] is used for watermark, the kernel judges this zone should
not be used because pages_free(1355) is smaller than watermark + protection[2]
(4 + 2004 = 2008). If this protection value is 0, this zone would be used for
normal page requirement. If requirement is DMA zone(index=0), protection[0]
(=0) is used.

zone[i]'s protection[j] is calculated by following expression.

(i < j):
  zone[i]->protection[j]
  = (total sums of managed_pages from zone[i+1] to zone[j] on the node)
    / lowmem_reserve_ratio[i];
(i = j):
   (should not be protected. = 0;
(i > j):
   (not necessary, but looks 0)

The default values of lowmem_reserve_ratio[i] are

    256 (if zone[i] means DMA or DMA32 zone)
    32  (others).

As above expression, they are reciprocal number of ratio.
256 means 1/256. # of protection pages becomes about "0.39%" of total managed
pages of higher zones on the node.

If you would like to protect more pages, smaller values are effective.
The minimum value is 1 (1/1 -> 100%).

  • max_map_count

This file contains the maximum number of memory map areas a process
may have. Memory map areas are used as a side-effect of calling
malloc, directly by mmap and mprotect, and also when loading shared
libraries.

While most applications need less than a thousand maps, certain
programs, particularly malloc debuggers, may consume lots of them,
e.g., up to one or two maps per allocation.

The default value is 65536.

  • memory_failure_early_kill

控制出现在后台被硬件检测出来的、内核无法处理的、未修正的内存错误(典型的是在一个内存模块中的2bit错误)时如何杀死后台进程。
在某些情况下(例如页仍然在disk上面有一个备份)内核会处理这个错误而不影响任何应用程序。但是如果没有最新的数据备份,那么就会杀死进程来防止数据错误的传播。
1:在一检查到错误时就杀死所有的出现错误并且没有可重新加载的页面映射的进程。
注意,对于少数类型的页面,不支持这个操作,例如内核内部分配的数据和swap cache,但是大部分页面都支持这个操作。
0:从所有进程中删除这个错误页面,并且杀死想要访问这个页面的进程。
kill是通过使用BUS_MCEERR_AO的可捕获的SIGBUS来完成的,因此进程可以对此进行处理。
这只对一些有先进的机器检查处理的结构有效,并且依赖于硬件的性能。
应用程序可以通过PR_MCE_KILL来覆盖这个设置。

  • memory_failure_recovery

enable 内存错误修复
1: 尝试修复
0: 在内存错误的时候总是panic

  • min_free_kbytes

这个参数是用来使Linux VM保留的free memory的最小值,单位是kb.
VM使用这个值来计算系统中的每个lowmem zone 的watermark[WMARK_MIN]的值。

每个lowmem zone都会获得一个预留的基于zone本身大小的free memory。

为了来满足PF_MEMALLOC的内存分配,需要一些一些最低限度的memory;如果你把这个值设置为小于1024KB,那你的系统会很容易broken,并且在高负载下很容易死锁。
把这个值设置很大的话会马上出发OOM(out of memory)机制。

  • mmap_min_addr

  • mmap_rnd_bits

  • mmap_rnd_compat_bits

  • nr_hugepages

  • nr_overcommit_hugepages

  • oom_dump_tasks

  • oom_kill_allocating_task

  • overcommit_kbytes

  • overcommit_memory

  • overcommit_ratio

  • page-cluster

  • panic_on_oom

  • percpu_pagelist_fraction

  • stat_interval

  • stat_refresh

  • swappiness

这个值是用来控制内核交换内存页面的倾向程度。这个值大,那么更倾向于交换;这个值小,就会较少交换。0表示kernel一直到可用内存低于zone的高水位才开始交换。默认值是60。

  • user_reserve_kbytes

  • vfs_cache_pressure

  • watermark_scale_factor

独特见解