当前位置: 首页 > news >正文

详细介绍Linux 内存管理 匿名页面和page cache页面有什么区别?

Linux 内存管理:匿名页面 vs Page Cache 页面深度解析

 

在 Linux 内存管理中,匿名页面 (Anonymous Pages) 和 页面缓存 (Page Cache) 是两种核心内存类型,它们在物理内存中存储不同类型的数据,并由不同的内核机制管理。下面从 5 个维度进行详细对比:

 

1. 核心概念对比

 

特性 匿名页面 页面缓存

 

数据来源 用户进程动态内存分配 文件系统内容缓存

 

典型内容 堆、栈、共享内存、mmap(MAP_ANON) 文件内容、目录、块设备数据

 

存储位置 RAM RAM (文件数据的缓存副本)

 

生命周期 与进程共存 可长期存在(直到缓存淘汰)

 

后备存储 交换空间 (Swap) 磁盘文件

 

管理对象 struct anon_vma struct address_space

 

页表项标志 VM_SHARED 和 VM_PRIVATE 无特定标志

 

2. 使用场景对比

 

匿名页面场景

 

// 动态内存分配

void *heap_mem = malloc(1024); // glibc底层使用brk/sbrk

 

// 栈内存

int stack_var = 42;

 

// mmap匿名映射

void *anon_mem = mmap(NULL, 8192, 

                      PROT_READ|PROT_WRITE, 

                      MAP_PRIVATE|MAP_ANONYMOUS, 

                      -1, 0);

       

 

页面缓存场景

 

// 文件读写

int fd = open("data.txt", O_RDWR);

char buf[4096];

read(fd, buf, 4096); // 数据加载到page cache

 

// mmap文件映射

void *file_mem = mmap(NULL, 8192, 

                      PROT_READ|PROT_WRITE, 

                      MAP_SHARED, 

                      fd, 0);

 

3. 内核数据结构对比

 

匿名页面反向映射       

 

struct anon_vma {

    struct rw_semaphore rwsem; // 读写锁

    atomic_t refcount; // 引用计数

    struct anon_vma_chain *root;

};

 

页面缓存组织

 

struct address_space {

    struct inode *host; // 所属inode

    struct xarray i_pages; // 页缓存树

    struct rw_semaphore i_mmap_rwsem;

    unsigned long nrpages; // 缓存页数

};

 

4. 缺页异常处理流程对比

 

匿名页面缺页处理 (do_anonymous_page)

 

触发缺页

 

是否为写访问?

 

-->分配新物理页-->初始化页面内容为0-->建立页表映射

 

-->映射零页

 

页面缓存缺页处理 (filemap_fault)

 

触发缺页

 

页面是否在缓存中?

 

-->映射缓存页

 

-->预读策略-->从磁盘读取数据-->创建新缓存页-->建立页表映射

 

5. 回收机制对比

 

匿名页面回收

 

通过 kswapd 扫描 LRU_INACTIVE_ANON 列表

 

使用交换子系统的反向映射 (try_to_unmap)

 

写入交换空间后释放物理页

 

页面缓存回收

 

通过 kswapd 扫描 LRU_INACTIVE_FILE 列表

 

干净页面直接释放

 

脏页触发回写机制 (writepages)

 

实战代码分析:两种页面行为对比

 

#include <stdio.h>

#include <stdlib.h>

#include <sys/mman.h>

#include <fcntl.h>

#include <unistd.h>

 

#define SIZE (2 * 1024 * 1024) // 2MB

 

int main() {

    // 场景1: 匿名页面操作

    char *anon_mem = mmap(NULL, SIZE, 

                         PROT_READ | PROT_WRITE,

                         MAP_PRIVATE | MAP_ANONYMOUS, 

                         -1, 0);

    

    // 写入数据(触发物理页分配)

    for (int i = 0; i < SIZE; i += 4096) 

        anon_mem[i] = 'A';

    

    printf("匿名页已分配\n");

    

    // 场景2: Page Cache操作

    int fd = open("test.dat", O_RDWR | O_CREAT, 0666);

    ftruncate(fd, SIZE); // 创建2MB文件

    

    char *file_mem = mmap(NULL, SIZE, 

                         PROT_READ | PROT_WRITE,

                         MAP_SHARED, 

                         fd, 0);

    

    // 写入数据(进入page cache)

    for (int i = 0; i < SIZE; i += 4096)

        file_mem[i] = 'B';

    

    printf("Page Cache已填充\n");

    msync(file_mem, SIZE, MS_SYNC); // 强制回写磁盘

    

    // 查看内存统计

    system("grep -E 'AnonPages|PageCache' /proc/meminfo");

    

    // 释放资源

    munmap(anon_mem, SIZE);

    munmap(file_mem, SIZE);

    close(fd);

    

    // 查看回收后状态

    system("grep -E 'AnonPages|PageCache' /proc/meminfo");

    

    return 0;

}

 

输出分析:

 

匿名页已分配

Page Cache已填充

AnonPages: 2048 kB # 匿名页占用

PageCache: 2048 kB # 页面缓存占用

 

# 释放后

AnonPages: 0 kB # 立即归零

PageCache: 16 kB # 元数据残留

 

6. 高级行为对比

 

行为 匿名页面 页面缓存

 

预读机制 无 文件系统级预读 (readahead)

 

透明大页(THP) 支持 (MADV_HUGEPAGE) 部分支持(依赖文件系统)

 

内存回收优先级 高 (vm.swappiness控制) 低 (vm.vfs_cache_pressure控制)

 

脏页处理 必须换出到swap 可延迟回写到文件系统

 

共享机制 写时复制 (COW) 直接共享

 

7. 性能优化技巧

 

匿名页面优化

 

// 1. 使用大页

madvise(anon_mem, SIZE, MADV_HUGEPAGE);

 

// 2. 禁用交换

mlock(anon_mem, SIZE); // 防止被换出

 

页面缓存优化

 

// 1. 预读设置

readahead(fd, 0, 4 * 4096); // 预读4个页面

 

// 2. 绕过缓存

int fd = open("file.dat", O_DIRECT); // 直接IO

 

 

总结:核心差异表

 

维度 匿名页面 页面缓存

 

数据来源 进程动态创建 存储设备文件

 

内核管理 anon_vma链 + swap address_space树 + 回写机制

 

缺页成本 低(零页或新分配) 高(可能触发磁盘IO)

 

生命周期 绑定进程生命周期 与文件缓存策略相关

 

共享开销 高(COW复制) 低(直接共享)

 

回收影响 强制swap-out(性能损失大) 可能仅丢失缓存(性能损失小)

 

理解这些差异对于开发高性能应用和诊断内存问题至关重要。通过合理选择内存类型,可以显著优化程序性能并减少系统开销。

http://www.dtcms.com/a/354922.html

相关文章:

  • Mybatis 与 Springboot 集成过程详解
  • vue有哪些优缺点
  • 前端实现Linux查询平台:打造高效运维工作流
  • 从图卷积网络(GCN)到简化图卷积网络(SGC)的对话
  • RAG系统深度优化全攻略:从理论到实践的高性能实现
  • 【C语言16天强化训练】从基础入门到进阶:Day 14
  • NVFP4量化技术深度解析:4位精度下实现2.3倍推理加速
  • 内网对抗-红日靶场4通关详解
  • 财务数据报销画像技术实现:从数据采集到智能决策的全流程解析
  • 2025docker快速部署Nginx UI可视化管理平台
  • Unity3d使用SerialPortUtilityPro读取串口数据
  • Linux(一) | 初识Linux与目录管理基础命令掌握
  • Libvio 访问异常排查指南
  • 2021/07 JLPT听力原文 问题一 2番
  • 【python】@staticmethod装饰器
  • nginx 配置文件初识全局块、events、http、server、location 的层级关系
  • SDK、JDK、JRE、JVM的区别
  • JSON 快速上手:语法解析与应用实例
  • 【VSCode】使用VSCode打开md文件以及转化为PDF
  • 打工人日报#20250828
  • HTTP 分块传输编码:深度解析与报文精髓
  • 第21节:环境贴图与PBR材质升级——构建电影级真实感渲染
  • Java 实现HTML转Word:从HTML文件与字符串到可编辑Word文档
  • 腕上智慧健康管家:华为WATCH 5与小艺的智美生活新范式
  • 使用EasyExcel实现Excel单元格保护:自由锁定表头和数据行
  • mac电脑双屏显示时程序坞跑到副屏的解决方法
  • 吱吱企业通讯软件以安全为基,搭建高效的通讯办公平台
  • ckman部署的clickhouse,节点迁移
  • 微算法科技(NASDAQ:MLGO)推出创新型混合区块链共识算法,助力物联网多接入边缘计算
  • [论文阅读] 人工智能 + 软件工程 | 告别“隐藏陷阱”:领域预训练模型SmartBERT如何赋能智能合约安全