内存管理-11-buddy伙伴子系统-2-Per-CPU页帧缓存

基于msm-5.4

一、概述

1. 实现背景

buddy子系统管理的物理页面,绝大多数都是放在 zone::free_area[] 中的链表中,少部分放在 zone::lowmem_reserve[] 中。还有少量页面放在
zone::__percpu pageset 这个每CPU变量中,每种迁移类型也都对应一个链表,但是没有order,都是单页大小的内存块。

由于前两个部分对所有CPU来说是全局的,链表的维护需要拿锁,这个同步带来开销。现在多核CPU是有多级缓存的,只有L1是私有的,L2/L3都是公有的,不同的CPU去访问同一个变量的时候,又涉及到缓存的同步刷新问题,这也会带来一定的开销。

使用本地缓存的页面不需要去申请锁,单个物理页面的申请释放是最频繁的,如果将单个物理页面的申请与释放做成一个每CPU的缓存,这样就不需要去拿全局锁了。Per-CPU页帧缓存的目的就是提升申请物理内存的性能,减少锁和cache缓存同步带来的开销。


2. 实现原理

struct zone 中有一个每CPU的 pageset 成员。

复制代码
struct zone {
    struct per_cpu_pageset __percpu *pageset;
}

struct per_cpu_pageset {
    struct per_cpu_pages pcp;
    s8 stat_threshold;
    s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];
};

struct per_cpu_pages {
    int count;        //lists链表中页面的个数
    int high;        //高水位,需要清空
    int batch;        //伙伴块添加/删除的大小
    struct list_head lists[MIGRATE_PCPTYPES]; //每个迁移类型一个链表,链表上的页面都是单个物理页
};
复制代码

在释放单个物理页的时候,不会释放给伙伴系统,而是直接释放到自己的本地 per_cpu_pages::lists 链表上。等到下次再申请单个物理页面时,首先去本地链表上去拿,若拿不到再到全局伙伴系统中去拿。

这个本地链表上缓存的单个物理页面的个数不是无限增加的,当超过 _watermark[] 水位值,伙伴系统中页面数较少的时候,会再将每CPU的页缓存释放到伙伴系统的全局链表上。

 

posted on   Hello-World3  阅读(65)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示