页面回收之shrink_zone的实现

本文深入解析了Linux内存管理系统中的页面回收机制,重点介绍了shrink_zone函数及其关键子过程shrink_active_list与shrink_inactive_list的工作原理。通过这些过程,系统能够有效地平衡活动内存与非活动内存,从而实现内存资源的有效利用。

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

页面回收的最重要的函数即:shrink_zone,其主要工作就是shrink_active_list和shrink_inactive_list。
        在shrink_zone中,如果该zone中需要扫描到的active和inactive的内存大于swap的阈值,即32个物理页面,则开始进行回收,否则不回收。
        shrink_active_list:移动一部分active中的页面到inactive中
        shrink_inactive_list
:释放inactive的内存。
        在shrink_active_list中:
                1.    
lru_add_drain();目的是将per cpu中的页面放入到LRU链表中(默认放到对应zone的inactive_list中),per cpu的页面是基于pagevec,最多缓存14个。
                2.    isolate_lru_pages中lru中隔离出一定量的页面(在锁(&zone->lru_lock)内,然后批量处理,pagevec的思想)放到临时链表中,依次遍历该临时链表,如果其中的page有映射,并且referenced为1,则说明该页面刚被访问过,因此不能回收,还会被放入到临时的active链表中,其余的被放入到临时inactive中。
                3.    然后批量处理临时的active和临时的inactive链表,回归中各自对应的zone的active_list和inactive_list中。
        在shrink_inactive_list中:
                1.    类似active的处理,将分离出的页面放到临时链表page_list中。
                2.    shrink_page_list将临时链表中的页面处理,依次按照页面的状态,逐一处理(如dirty,writeback,有需要还要释放bh)。
                3.    将需要释放的页面放到临时向量表中,然后批量释放__pagevec_release_nonlru(&freed_pvec);其pagevec_free将页面返还给伙伴系统中。
                4.    执行完前三步,还有页面没有被回收,则将其再放回LRU中,zone的active_list和inactive_list
<think>我们正在讨论的是Linux内核中的内存回收机制,特别是`shrink_anon.c`文件。根据用户提供的路径`/vendor/bsp/kernel5.15/drivers/unisoc_platform/mm/reclaim`,这看起来是展讯(Unisoc)平台对内核内存回收机制的定制实现。`shrink_anon.c`文件通常负责匿名页(anonymouspages)的回收。###1.**匿名页回收的背景**在Linux内核中,当系统内存不足时,会触发内存回收(Reclaim)机制。回收的对象主要包括两种内存:-**文件页(Filepages)**:有文件背景的页面(例如文件缓存),可以直接写回磁盘。-**匿名页(Anonymouspages)**:没有文件背景的页面(例如进程的堆栈数据),需要交换(swap)到磁盘。`shrink_anon.c`主要处理匿名页的回收。###2.**`shrink_anon.c`的核心功能**该文件实现了匿名页的扫描和回收算法,主要包含以下关键部分:####a.**LRU链表管理**匿名页被组织在LRU(LeastRecentlyUsed)链表中。`shrink_anon.c`通过扫描LRU链表来寻找可以回收页面[^3]。####b.**页面回收策略**-**页面选择算法**:通过扫描LRU链表,选择最近最少使用的页面进行回收。-**交换(Swap)**:将选中的匿名页写入交换分区(或交换文件),然后释放物理内存。####c.**回收流程**1.**扫描LRU链表**:从LRU链表的尾部开始扫描,选择候选页面。2.**隔离页面**:将选中的页面从LRU链表中暂时隔离。3.**尝试回收**:-如果页面是干净的(clean),则直接释放。-如果是脏的(dirty),则尝试写回交换空间。4.**处理结果**:根据回收结果,将页面放回LRU链表或释放。###3.**关键函数分析**在`shrink_anon.c`中,以下函数通常是核心:-`shrink_anon_list()`:负责扫描和回收匿名页链表。-`isolate_anon_pages()`:从LRU链表中隔离出候选页面。-`try_to_unmap_anon()`:尝试解除页面的映射,为回收做准备。###4.**与展讯平台的关联**由于该文件位于`/vendor/bsp/kernel5.15/drivers/unisoc_platform/mm/reclaim`,说明展讯平台可能对标准内核的匿名页回收机制做了定制,例如:-**优化移动设备的内存回收**:移动设备对内存和功耗敏感,展讯可能调整了回收策略以减少功耗或提升性能。-**适应低内存设备**:针对低内存设备,调整回收阈值或算法。###5.**内存回收的触发**匿名页回收通常由以下机制触发:-**直接回收(DirectReclaim)**:当分配内存失败时,同步触发回收。-**kswapd守护进程**:在后台异步回收内存,维护内存水位[^3]。###6.**性能与调优**-**回收效率**:过度回收会导致交换I/O,影响性能。-**参数调优**:通过`/proc/sys/vm`下的参数(如`swappiness`)调整匿名页回收的积极性。---###示例:匿名页回收流程```c//伪代码:shrink_anon_list的核心逻辑voidshrink_anon_list(structlist_head*page_list){while(!list_empty(page_list)){page=list_last_entry(page_list,structpage,lru);//解除页面映射if(try_to_unmap(page)){//写回交换空间if(page_is_dirty(page))writeback_to_swap(page);//释放页面free_page(page);}}}```---§§相关问题§§1.如何调整`swappiness`参数以平衡匿名页和文件页的回收?2.在无交换分区的系统中,匿名页回收如何处理?3.`kswapd`守护进程如何与`shrink_anon.c`交互?4.展讯平台在`shrink_anon.c`中做了哪些优化?5.如何监控匿名页回收的性能?[^1]:匿名页与文件页的区别[^3]:kswapd守护进程与LRU链表管理</think>### `shrink_anon.c`文件功能解析 `shrink_anon.c`是Linux内核中**匿名页回收机制**的核心实现文件,位于内存管理子系统。其核心功能是回收匿名内存页(Anonymous Pages),即进程堆、栈等无文件背景的内存页。主要作用如下: --- #### 1. **匿名页回收算法实现** - **LRU链表扫描** 通过扫描全局`LRU_ANON`链表(包含所有匿名页),按最近最少使用(LRU)策略选择回收候选页: ```c list_for_each_entry_safe(page, tmp, &lru_list, lru) { if (isolate_lru_page(page)) continue; // 隔离可回收页 nr_reclaimed += reclaim_page(page); // 执行回收 } ``` 优先回收长时间未访问的冷页[^3]。 - **交换空间回写** 匿名页需先写入交换分区才能回收物理内存: ```c if (PageAnon(page) && PageDirty(page)) { add_to_swap_cache(page); // 加入交换缓存 swap_writepage(page); // 写入交换设备 } ``` #### 2. **内存压力响应机制** - **直接回收(Direct Reclaim)** 当进程分配内存时触发`__alloc_pages_direct_reclaim()`,调用`shrink_anon_list()`同步回收匿名页: ```c unsigned long shrink_anon_list(struct list_head *page_list) { // 计算需回收页数:available = free - (lowmem_reserve + high_wmark) [^1] target = calculate_reclaim_target(zone); while (nr_reclaimed < target) { ... } } ``` - **kswapd后台回收** 内核线程`kswapd`周期性检查内存水位,通过`balance_pgdat()`调用匿名页回收: ```c kswapd()->balance_pgdat()->shrink_node()->shrink_anon(); ``` 使用`kswapd_wait`队列管理回收任务[^3]。 #### 3. **回收策略控制** - **Swappiness参数** 通过`/proc/sys/vm/swappiness`(默认值60)控制匿名页与文件页回收比例: ```c if (sc->priority < swappiness) anon_target = (sc->nr_to_reclaim * sc->swappiness) / 100; ``` 值越高越倾向回收匿名页。 - **NUMA感知回收** 针对多核架构优化,优先回收本地内存节点的页: ```c for_each_zone_zonelist_nodemask(zone, z, zonelist, sc->reclaim_idx) { shrink_zone(zone, sc); // NUMA节点局部性回收 } ``` #### 4. **展讯平台优化** 在`/vendor/bsp/kernel5.15/drivers/unisoc_platform/mm/reclaim`路径下的实现通常包含: - **低内存设备适配** 调整回收阈值和扫描粒度,适应移动设备小内存场景。 - **功耗优化** 减少回收操作频率,合并I/O请求以降低CPU唤醒次数。 - **ZRAM压缩集成** 与ZRAM驱动协同,实现匿名页压缩而非交换到慢速存储。 --- #### 典型工作流程 ```mermaid graph TD A[内存分配失败] --> B{直接回收触发?} B --是--> C[shrink_anon_list同步回收] B --否--> D[kswapd周期性检查] D --> E{内存水位低于low?} E --是--> F[shrink_anon异步回收] C & F --> G[隔离LRU匿名页] G --> H{页是否脏?} H --是--> I[写入交换空间] H --否--> J[释放物理页] I --> J ``` --- #### 性能影响与监控 - **I/O瓶颈** 大量匿名页回收可能引发交换I/O风暴,可通过`sys.dm_io_pending_io_requests`监控[^4]。 - **回收效率指标** `sar -B`输出的`pgscank`/`pgscand`显示匿名页扫描速率。 - **调优建议** 增加交换空间或ZRAM大小可降低回收频率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值