这个时候最简单有效的就是自己手动释放内存,或者写一个释放内存的脚本去做这个事情.

linux中的 是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段。也就是说可以通过修改 /proc 中的文件,来对当前kernel的行为做出调整。那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。

首先,查看/proc/sys/vm/drop_caches的值:

默认值为0. 这里需要解释下drop_caches的值可以是0-3之间的数字,代表不同的含义:

0:不释放(系统默认值).

1:释放页缓存.

2:释放dentries和inodes.

3:释放所有缓存.

然后,运行sync命令.

  1. > sync

手动执行sync命令(描述:sync 命令运行 sync 子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件)最后,输入手动释放内存的命令.

  1. > echo 1 > /proc/sys/vm/drop_caches

等到我们释放完内存后改回去让系统重新自动分配内存.

  1. > echo 0 >/proc/sys/vm/drop_caches

在Linux系统下,我们一般不需要去释放内存,因为系统已经将内存管理的很好。但是,有的时候内存会被缓存占用掉,导致系统使用SWAP空间影响性能,例如当你在linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching。,此时就需要执行释放内存(清理缓存)的操作了。

Linux系统的缓存机制设计的很棒,会针对dentry(用于VFS,加速文件路径名到inode的转换)Buffer Cache(针对磁盘块的读写)Page Cache(针对文件inode的读写)进行缓存操作。在进行了大量文件操作之后,缓存会把内存资源基本用光。然而此时呢我们文件操作已经完成,这部分缓存已经用不到了。这个时候,我们难道只能眼睁睁的看着缓存把内存空间占据掉吗?所以,我们还是有必要来手动进行Linux下释放内存的操作,其实也就是释放缓存的操作了。

/proc是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段.也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整.那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。要达到释放缓存的目的,我们首先需要了解下关键的配置文件/proc/sys/vm/drop_caches。这个文件中记录了缓存释放的参数,默认值为0,也就是不释放缓存。

一般复制了文件后,可用内存会变少,都被cached占用了,这是linux为了提高文件读取效率的做法:为了提高磁盘存取效率, Linux做了一些精心的设计, 除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer CachePage Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。”

释放内存前先使用sync命令做同步,以确保文件系统的完整性,将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件。否则在释放缓存的过程中,可能会丢失未保存的文件。

然后通过:

  1. > free -m
  2. total used free shared buff/cache available
  3. Mem: 15883 965 1057 2 13860 10172
  4. Swap: 0 0 0
  • total 内存总数
  • used 已经使用的内存数,一般情况这个值会比较大,因为这个值包括了cache 应用程序使用的内存
  • free 空闲的内存数
  • shared 多个进程共享的内存总额
  • buffers缓存,主要用于目录方面,inode值等(ls大目录可看到这个值增加)
  • cached 缓存,用于已打开的文件

这里的可以用内存就是free memory buffers cached

top命令用来查看具体进程消耗的内存空间。

  1. > top
  2. top - 22:49:09 up 6 days, 11:04, 1 user, load average: 0.05, 0.11, 0.13
  3. Tasks: 233 total, 1 running, 232 sleeping, 0 stopped, 0 zombie
  4. %Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
  5. KiB Mem : 19264560 total, 5250212 free, 820192 used, 8794156 buff/cache
  6. KiB Swap: 0 total, 0 free, 0 used. 10768300 avail Mem
  7. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
  8. 4709 root 20 0 3101008 119788 35696 S 1.3 0.7 182:29.21 kubelet
  9. 1527 root 20 0 3362068 113276 25004 S 1.0 0.7 192:35.61 dockerd
  10. 1849 root 20 0 2401924 53416 12728 S 0.7 0.3 35:12.78 docker-containe
  11. 18139 root 20 0 162124 2408 1612 R 0.7 0.0 0:00.34 top
  12. 3190 root 20 0 700332 46788 5284 S 0.3 0.3 7:27.10 salt-minion
  13. 11669 root 20 0 142088 27076 13304 S 0.3 0.2 6:51.16 kube-proxy
  14. 17152 root 10 -10 436896 2748 2264 S 0.3 0.0 3:39.81 AliSecGuard
  15. 1 root 20 0 44608 4984 2588 S 0.0 0.0 2:05.33 systemd
  16. 3 root 20 0 0 0 0 S 0.0 0.0 0:02.84 ksoftirqd/0
  17. 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
  18. 7 root rt 0 0 0 0 S 0.0 0.0 0:01.97 migration/0
  19. 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
  20. 9 root 20 0 0 0 0 S 0.0 0.0 4:21.17 rcu_sched
  21. 10 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 lru-add-drain
  22. 11 root rt 0 0 0 0 S 0.0 0.0 0:01.44 watchdog/0
  23. 12 root rt 0 0 0 0 S 0.0 0.0 0:01.21 watchdog/1
  24. 13 root rt 0 0 0 0 S 0.0 0.0 0:06.15 migration/1

通过%MEM列,就可以查看哪几个进程占用了大量的内存,在缓解内存不足的紧急情况时,可以终止这些占用内存较多的进程。

top命令中有以下与内存相关的数据列:

  1. PID:进程的ID.
  2. USER:进程所有者.
  3. PR:进程的优先级别,越小越优先被执行.
  4. NInice:值.
  5. VIRT:进程占用的虚拟内存.
  6. RES:进程占用的物理内存.
  7. SHR:进程使用的共享内存.
  8. S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数.
  9. %CPU:进程占用CPU的使用率.
  10. %MEM:进程使用的物理内存和总内存的百分比.
  11. TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。.
  12. COMMAND:进程启动命令名称.

使用free命令可以查看内存的总体使用,显示的内容也包括交换分区的大小,可以使用swapon,swapoff,命令开启或关闭交换空间,交换空间是磁盘上的文件,并不是真正的内存空间。

此时交换分区显示全为0,说明系统没有开启交换分区。swapon命令可以启用交换分区。当内存不足时,系统会选择通过将部分不常被访问的内存页交换到内存空间,或者删除部分cache的文件来释放内存空间。

系统的可用内存一般等于物理内存 + 交换分区。交换分区在磁盘上, 因此速度比内存读写要慢得多。

交换分区实际上就是磁盘上的文件,可以通过mkswap命令来创建交换空间。

  1. > slabtop

slab系统用来处理系统中比较小的元数据,如文件描述符等,进而组织内核态的内存分配。

一个slab包含多个object,例如dentry这些数据结构就是object,可以通过slabtop命令查看系统中活动的object的数量与内存占用情况,从而了解哪些数据结构最占用内核态的内存空间。

例如:使用slabtop命令查看内核数据结构及内存占用

  1. Active / Total Objects (% used) : 1222616 / 1575898 (77.6%)
  2. Active / Total Slabs (% used) : 39945 / 39945 (100.0%)
  3. Active / Total Caches (% used) : 67 / 125 (53.6%)
  4. Active / Total Size (% used) : 276332.00K / 318115.77K (86.9%)
  5. Minimum / Average / Maximum Object : 0.01K / 0.20K / 15.75K
  6. OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
  7. 848211 516003 60% 0.10K 21749 39 86996K buffer_head
  8. 75300 73560 97% 0.63K 3012 25 48192K proc_inode_cache
  9. 70224 70224 100% 0.96K 2128 33 68096K ext4_inode_cache
  10. 52530 50791 96% 0.04K 515 102 2060K ext4_extent_status
  11. 30702 29066 94% 0.19K 731 42 5848K kmalloc-192
  12. 27076 22278 82% 0.55K 967 28 15472K radix_tree_node
  13. 26532 26532 100% 0.11K 737 36 2948K sysfs_dir_cache
  14. 20910 20910 100% 0.05K 246 85 984K shared_policy_node
  15. 12712 12712 100% 0.57K 454 28 7264K inode_cache
  16. 11536 10815 93% 0.07K 206 56 824K anon_vma
  17. 9088 7840 86% 0.03K 71 128 284K kmalloc-32
  18. 6752 3567 52% 0.25K 211 32 1688K kmalloc-256
  19. 6656 6656 100% 0.02K 26 256 104K kmalloc-16
  20. 6560 4747 72% 0.12K 205 32 820K kmalloc-128
  21. 6656 6656 100% 0.02K 26 256 104K kmalloc-16

这里通常需要关注有两点:

  1. 哪些数据结构的内存占用最大,
  2. 哪些类型的数据结构对应的object最多,比如inode多代表文件系统被大量引用等。

该交互命令支持的选项与排序标准有:

  1. 选项:
  2. --delay=n, -d n 每隔n秒刷新信息
  3. --once, -o 只显示一次
  4. --sort=S, -s S 按照S排序,其中S为排序标准
  5. 排序标准(shift + 对应的键):
  6. a:根据active objects数量高低排序
  7. b:根据 objects / slab高低来排序
  8. c:根据cache大小排序
  9. l:根据slab数量排序
  10. v:根据active slabs数量排序
  11. n:按 name 排序
  12. o:按照 objects 数量排序
  13. p:按照 pages / slab 的值排序
  14. s:按照 object 大小排序
  15. u:按照 cache 使用量排序

vmstat命令可以查看内存使用的动态变化,

例如: 使用vmstat动态监视内存变动

其中vmstat N 代表每隔N秒更新一次数据。

  1. > sync //先将内存刷出,避免数据丢失
  2. > echo 1 > /proc/sys/vm/drop_caches //释放pagecache
  3. > echo 2 > /proc/sys/vm/drop_caches //释放dentryinode

通常情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的,虽然看上去可能比较小。当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,如用户量太大导致内存不足、发生应用内存溢出等情况,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了,所以说一般情况下linux都不用经常手动释放内存。