由于伙伴算法的存在,linux的内存势必出现碎片,虽然大多数时候不会对应用层产生影响,但是一旦遇到需要连续内存的情况就歇逼了;

这时候就需要整理内存碎片

实际问题场景:

  1. cat /proc/buddyinfo
  2. Node 0, zone DMA 182 167 132 32 0 0 0 0 0 0 0
  3. Node 0, zone Normal 846 1998 1043 464 154 69 15 3 3 1 0

/proc/buddyinfo这个文件记录了物理内存的状态,linux会使用一个长度为11的链表维护pages

从这个文件可以看出DMA碎片化已经很严重了,大多数内存都变成page=1 page=2 page=4的小块连续内存;

此时需要整理内存;

触发内存碎片整理的三种方法:

内存分配时整理:

调用过程如下:
alloc_pages_slowpath
\
alloc_pages_direct_compact
\
__try_to_compact_pages
\
compact_zone_order
\
compact_zone

Kcompactd后台进程进行整理

调用过程如下:
kcompactd -> kcompactd_do_work -> compact_zone

手动触发碎片整理

触发方式:
echo 1 > /sys/devices/system/node/node0/compact
(sysfs_compact_node -> compact_node -> compact -> compact_zone)

echo 1 > /proc/sys/vm/compact_memory
(sysctl_compaction_handler -> compact_nodes -> compact -> compact_zone)

但是很不幸,手动触发内存碎片整理的接口在openwrt中并没有被发现