内存管理-31-内存统计-1-初探

基于msm-5.4

一、概述

Linux内核为了帮助大家从宏观上把握系统内存的使用情况,在几大核心数据结构上都有相应的统计计数,如物理页面使用情况、伙伴系统分配情况、内存管理区的物理页面使用情况等。

1. vm_stat 计数值

内存管理模块定义了三个全局的 vm_stat 计数值

//include/linux/vmstat.h
extern atomic_long_t vm_zone_stat[NR_VM_ZONE_STAT_ITEMS];
extern atomic_long_t vm_numa_stat[NR_VM_NUMA_STAT_ITEMS]; //默认不使能CONFIG_NUMA,这个不存在
extern atomic_long_t vm_node_stat[NR_VM_NODE_STAT_ITEMS];

内存管理区中包含与页面相关的计数值:

struct zone {
    atomic_long_t        vm_stat[NR_VM_ZONE_STAT_ITEMS];
    atomic_long_t        vm_numa_stat[NR_VM_NUMA_STAT_ITEMS];
}

内存节点数据结构中包含与页面相关的计数值:

typedef struct pglist_data {
    atomic_long_t        vm_stat[NR_VM_NODE_STAT_ITEMS];
}

enum zone_stat_item:

enum zone_stat_item {
    NR_FREE_PAGES, //空闲页面数
    NR_ZONE_LRU_BASE, //用于 LRU_BASE 的统计,LRU链表是从 LRU_BASE 开始标记的。##### 注释: 仅用于压缩和回收重试。
    NR_ZONE_INACTIVE_ANON = NR_ZONE_LRU_BASE, //不活跃匿名页面数量
    NR_ZONE_ACTIVE_ANON, //活跃匿名页面数量
    NR_ZONE_INACTIVE_FILE, //不活跃文件映射页面数量
    NR_ZONE_ACTIVE_FILE, //活跃文件映射页面数量
    NR_ZONE_UNEVICTABLE, //不可回收页面数量
    NR_ZONE_WRITE_PENDING,    //脏页、正在回写以及不稳定的页面数量
    NR_MLOCK,        //使用 mlock() 锁住的页面。注释:找到已锁定的页面并将其移出 LRU。
    NR_PAGETABLE,    //用于页表的页面数量
    NR_KERNEL_STACK_KB,    //用于内核栈的页面数量。注释: 以KB为单位
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
    NR_KERNEL_SCS_BYTES,    /* measured in bytes */
#endif
    NR_BOUNCE, //跳跃页面的数量
#if IS_ENABLED(CONFIG_ZSMALLOC)
    NR_ZSPAGES, //用于 zsmalloc 机制的页面数量
#endif
    NR_FREE_CMA_PAGES, //CMA中的空闲页面数量
    NR_VM_ZONE_STAT_ITEMS //zone中vm_stat计数值的项数
};

跳跃页面:在早期IA-32架构中,一些ISA总线的设备只能访问低端的16M内存,如DMA设备源地址在16M以下,而DMA设备的目标地址可能在16MB以上,因此需要在16M内存分配一个缓冲区来作为跳板,这明显会增加一次复制动作,这个缓冲区称为跳跃页面。

提供了几个接口来计算统计计数:

//include/linux/vmstat.h
static inline void zone_page_state_add(long x, struct zone *zone, enum zone_stat_item item)
{
    atomic_long_add(x, &zone->vm_stat[item]);
    atomic_long_add(x, &vm_zone_stat[item]);
}
static inline void node_page_state_add(long x, struct pglist_data *pgdat, enum node_stat_item item)
{
    atomic_long_add(x, &pgdat->vm_stat[item]);
    atomic_long_add(x, &vm_node_stat[item]);
}

提供了几个接口来获取统计计数:

//include/linux/vmstat.h
static inline unsigned long global_zone_page_state(enum zone_stat_item item)
{
    return atomic_long_read(&vm_zone_stat[item]);
}
static inline unsigned long global_node_page_state(enum node_stat_item item)
{
    return atomic_long_read(&vm_node_stat[item]);
}

static inline unsigned long zone_page_state(struct zone *zone, enum zone_stat_item item)
{
    return atomic_long_read(&zone->vm_stat[item]);
}
//mm/vmstat.c
unsigned long node_page_state(struct pglist_data *pgdat, enum node_stat_item item)
{
    return atomic_long_read(&pgdat->vm_stat[item]);
}

没有使能 CONFIG_NUMA, 使用的主要是全局的数组,见:

#define sum_zone_node_page_state(node, item) global_zone_page_state(item)
#define node_page_state(node, item) global_node_page_state(item)

 

posted on 2024-08-27 21:15  Hello-World3  阅读(26)  评论(0编辑  收藏  举报

导航