buddyinfo 内存碎片数据采集

本文介绍了一个名为buddyinfo.sh的Shell脚本,该脚本用于监控和展示Linux系统的内存分配情况,特别是不同层级的伙伴系统内存块状态。通过定时收集/proc/buddyinfo中的数据并进行计算,输出了各个层级的内存使用情况,有助于理解系统内存管理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不说了,上工具

#cat    buddyinfo.sh
#!/bin/sh
#****************************************************************#
# ScriptName: buddyinfo.sh
# Author: $SHTERM_REAL_USER@alibaba-inc.com
# Create Date: 2017-04-26 15:47
# Modify Author: $SHTERM_REAL_USER@alibaba-inc.com
# Modify Date: 2017-04-26 15:47
# Function:
#***************************************************************#

BC_MUTI(){
    #subtraction
    if [[ -n $1 && -n $2 ]];then
        res1=$(printf "%.2f" `echo "scale=2;($1*$2)"|bc`)
        echo $res1
    fi
}

MESG(){
  local GROUP="$1"
  local KEY=$2
  local VALUE=$3
  local MEASURE=$4

  if [[ -n $VALUE ]];then
      echo -e "$(date "+%F %H:%M:%S"),$GROUP,$KEY,$VALUE,$MEASURE"  >> $REAL_LOG
      return 0
  fi
}

BC_BUDDY(){
    aa=$1
    bb=$2
    let "res1=$aa*2**$bb"
    echo $res1
}

CONVERT_BUDDY_VALUE(){
    start=$1
    MAX=`cat /proc/buddyinfo  | grep "Normal"| awk -F"Normal" '{print $2}'|awk '{print NF}'`
    MAX=`echo "$MAX - 1" | bc`
    buddy_values=`cat /proc/buddyinfo  | grep "Normal"| awk -F"Normal" '{print $2}'`
    array2=(
        $buddy_values
    )
  bb=`echo ${array2[@]:$start:$MAX}`

    count=0
    final_vvv=0
    for value in ${bb[@]};do
        vvv=`BC_BUDDY $value $count`
        count=`echo "$count +1 "|bc`
        final_vvv=`echo "$final_vvv + $vvv"|bc`
    done

    echo  $final_vvv
}

LOOP_VMSTAT(){
    while [[ 0 == 0 ]] ;do
        sleep 1
        CALCULATE_VMSTAT
    done
}

CALCULATE_VMSTAT(){
    timestamp=$(date "+%Y-%m-%d-%H:%M:%S")
    order1=`CONVERT_BUDDY_VALUE 1`
    order2=`CONVERT_BUDDY_VALUE 2`
    order3=`CONVERT_BUDDY_VALUE 3`
    order4=`CONVERT_BUDDY_VALUE 4`
    order5=`CONVERT_BUDDY_VALUE 5`
    order6=`CONVERT_BUDDY_VALUE 6`
    order7=`CONVERT_BUDDY_VALUE 7`
    order8=`CONVERT_BUDDY_VALUE 8`
    order9=`CONVERT_BUDDY_VALUE 9`
    order10=`CONVERT_BUDDY_VALUE 10`
    printf "%-20s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n" $timestamp $order1 $order2 $order3 $order4 $order5 $order6 $order7 $order8 $order9 $order10
}
main(){
     printf "%-20s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n" "timestamp" "order1" "order2" "order3" "order4" "order5" "order6" "order7" "order8" "order9" "order10"
     LOOP_VMSTAT
}
main
[root@jiangyi01.sqa.zmf /home/ahao.mah]
#sh   buddyinfo.sh
timestamp            order1  order2  order3  order4  order5  order6  order7  order8  order9  order10

2017-04-26-20:53:20  9952240 4975948 2487866 1243711 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:22  9952309 4975928 2487861 1243712 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:23  9952392 4975970 2487869 1243713 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:24  9952429 4975992 2487877 1243713 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:26  9952449 4975993 2487879 1243713 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:27  9952485 4975998 2487880 1243713 621496  309892  154207  76867   38313   19124
2017-04-26-20:53:28  9952490 4976003 2487883 1243715 621497  309892  154207  76867   38313   19124
2017-04-26-20:53:29  9952475 4975996 2487882 1243716 621498  309892  154207  76867   38313   19124
2017-04-26-20:53:31  9952404 4975956 2487881 1243716 621498  309892  154207  76867   38313   19124
2017-04-26-20:53:32  9952494 4975998 2487886 1243716 621498  309892  154207  76867   38313   19124

970272-20170426205416350-517314710.png

转载于:https://www.cnblogs.com/muahao/p/6770014.html

<think>嗯,用户问的是Linux如何解决内存碎片问题。我得先回忆一下内存碎片是什么,以及Linux的内存管理机制。内存碎片分为外部碎片和内部碎片,外部碎片是空闲内存分散,无法满足大块请求;内部碎片是分配的内存比实际需要的多,未被利用的部分。 首先,Linux使用伙伴系统(Buddy System)来管理物理内存。伙伴系统将内存分成不同大小的块,按2的幂次方组织。当需要分配内存时,伙伴系统会找到合适大小的块,如果找不到,就分裂更大的块。释放内存时,会合并相邻的空闲块,减少外部碎片。但伙伴系统可能无法完全避免碎片,特别是长时间运行后。 然后是slab分配器,用于管理内核对象的小内存分配。slab将内存分成不同大小的缓存,减少内部碎片。比如,经常分配的结构体如task_struct会被缓存,避免频繁申请释放导致的小块碎片。这样能提高效率,同时减少碎片。 还有页迁移(Page Migration)技术,在较新的内核版本中,特别是支持非均匀内存访问(NUMA)的系统,可以通过移动物理页来整理内存,减少碎片。这类似于磁盘整理,但需要硬件和内核支持。 内存碎片整理(Memory Compaction)也是一个机制,内核会定期或按需将已使用的页移动到一起,腾出连续的大块空间。这主要处理外部碎片,确保大块内存分配成功。 另外,虚拟内存机制通过分页和地址转换,让进程使用连续的虚拟地址,而物理内存可以分散。这样应用层感知不到物理碎片,但内核仍需处理物理连续的需求,如DMA缓冲区。 在用户空间,使用malloc和glibc的分配器,它们可能调用brk或mmap。glibc的ptmalloc通过维护多个内存池和空闲列表来优化小对象分配,减少碎片。但用户态的内存碎片问题更多依赖应用程序的设计,比如对象池、避免频繁分配释放小对象。 需要补充的是,Linux内核在2.6版本后引入了反碎片(anti-fragmentation)技术,将内存页按可移动性分类,如不可移动、可回收、可移动。这样在分配时,相同类型的页放在一起,便于后续整理和迁移,减少碎片。 还有OOM Killer在内存不足时终止进程,虽然不直接解决碎片,但释放内存可能间接帮助。此外,透明大页(Transparent Huge Pages, THP)尝试自动使用大页减少TLB压力,可能间接减少碎片需求。 不过,用户可能更关心实际应用中的表现,比如如何监控内存碎片。可以查看/proc/buddyinfo和/proc/slabinfo,或者使用工具如vmstat检查内存使用情况。对于需要大量连续内存的应用,如数据库,可能需要调整内核参数或使用大页配置。 总结时,要分点说明伙伴系统、slab、页迁移、内存碎片整理、虚拟内存的作用。同时,指出用户态和内核态的差异,以及监控工具的使用。可能用户遇到了性能问题,或者想优化系统,需要给出实际建议。</think>Linux 主要通过以下几种机制解决内存碎片问题,尤其针对**外部碎片**(空闲内存分散无法满足大块请求)和**内部碎片**(已分配内存未被充分利用)进行优化: --- ### **1. 伙伴系统(Buddy System)** - **核心机制**:将物理内存划分为不同大小的块(按 \(2^n\) 页为单位),每个块称为一个“伙伴”。 - 分配内存时,优先匹配最小满足需求的块;若没有,则拆分更大的块。 - 释放内存时,检查相邻块是否空闲,合并成更大的块(减少外部碎片)。 - **缺点**:长时间运行后可能仍有碎片,尤其是频繁分配释放不同大小的内存时。 -- ### **2. Slab 分配器** - **用途**:管理内核对象(如进程描述符、文件句柄等)的小内存分配。 - **优化内部碎片**: - 预先分配固定大小的内存块(Slab Cache),缓存常用对象。 - 避免频繁向伙伴系统请求小内存,减少内存浪费。 - **典型工具**:通过 `/proc/slabinfo` 查看 Slab 使用情况。 -- ### **3. 页迁移与内存碎片整理(Memory Compaction)** - **页迁移(Page Migration)**: - 将已分配的物理页移动到其他位置,合并出连续空闲区域。 - 需要内核配置 `CONFIG_MIGRATION` 和 `CONFIG_COMPACTION`。 - **触发时机**: - 内核自动在后台运行(`kswapd` 或 `kcompactd` 线程)。 - 显式触发:通过 `sysctl vm.compact_memory=1` 或写入 `/proc/sys/vm/compact_memory`。 -- ### **4. 反碎片分组(Anti-Fragmentation Grouping)** - **原理**:将内存页按“可移动性”分类(如不可移动、可回收、可移动)。 - 例如:内核数据结构(不可移动)、用户进程内存(可移动)。 - 分配时优先使用相同类型的页,便于后续迁移和整理。 --- ### **5. 虚拟内存机制** - **虚拟地址空间**: - 用户进程通过虚拟地址访问内存,物理内存可以是分散的(通过页表映射)。 - 对应用程序透明,解决“虚拟连续但物理不连续”的问题。 - **例外**:某些硬件(如 DMA)需要物理连续内存,依赖伙伴系统或预留大块内存。 --- ### **6. 透明大页(Transparent Huge Pages, THP)** - **目标**:减少页表项数量,提升内存访问效率,间接降低碎片化影响。 - 自动将小页(4KB)合并为大页(2MB 或 1GB)。 - 需内核支持并启用(通过 `/sys/kernel/mm/transparent_hugepage/enabled` 配置)。 --- ### **7. 用户态内存管理优化** - **glibc 的 `malloc` 实现**: - 使用 `brk`(扩展堆)和 `mmap`(匿名映射)分配内存。 - 通过维护空闲链表(`bins`)减少碎片,但过度优化可能导致内存浪费。 - **建议**: - 避免频繁分配/释放小对象(可使用内存池或对象池)。 - 使用 `jemalloc` 或 `tcmalloc` 替代默认 `malloc`(更积极的反碎片策略)。 --- ### **监控工具** 1. **查看外部碎片**: ```bash cat /proc/buddyinfo # 显示伙伴系统的空闲块分布(数值越大表示连续内存越多) ``` 2. **查看内部碎片(Slab)**: ```bash cat /proc/slabinfo # 显示 Slab 缓存的使用情况 ``` 3. **内存统计**: ```bash vmstat -m # 显示内核模块的内存使用 ``` --- ### **总结** Linux 通过**伙伴系统 + Slab 分配器**解决物理内存碎片,结合**页迁移、反碎片分组**动态整理内存。对于用户程序,虚拟内存机制隐藏了物理碎片,但需注意特殊场景(如 DMA)的物理连续需求。实际优化需结合监控工具分析和调整内核参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值