0

0

Linux kernel内存碎片防治技术:深入理解内存管理

WBOY

WBOY

发布时间:2024-02-12 09:54:15

|

1196人浏览过

|

来源于良许Linux教程网

转载

你是否曾经遇到过在linux系统中出现的各种内存问题?比如内存泄漏、内存碎片等等。这些问题都可以通过深入理解linux kernel内存碎片防治技术得到解决。

Linux kernel内存碎片防治技术:深入理解内存管理

Linux kernel组织管理物理内存的方式是buddy system(伙伴系统),而物理内存碎片正式buddy system的弱点之一,为了预防以及解决碎片问题,kernel采取了一些实用技术,这里将对这些技术进行总结归纳。

1 低内存时整合碎片

从buddy申请内存页,如果找不到合适的页,则会进行两步调整内存的工作,compact和reclaim。前者是为了整合碎片,以得到更大的连续内存;后者是回收不一定必须占用内存的缓冲内存。这里重点了解comact,整个流程大致如下:

__alloc_pages_nodemask
  -> __alloc_pages_slowpath
    -> __alloc_pages_direct_compact
      -> try_to_compact_pages
        -> compact_zone_order
          -> compact_zone
            -> isolate_migratepages
            -> migrate_pages
            -> release_freepages
并不是所有申请不到内存的场景都会compact,首先要满足order大于0,并且gfp_mask携带__

GFP_FS和__GFP_IO;另外,需要zone的剩余内存情况满足一定条件,kernel称之为“碎片指数”(fragmentation index),这个值在0~1000之间,默认碎片指数大于500时才能进行compact,可以通过proc文件extfrag_threshold来调整这个默认值。fragmentation index通过fragmentation_index函数来计算:

1. /*
2. \* Index is between 0 and 1000
3. *
4. \* 0 => allocation would fail due to lack of memory
5. \* 1000 => allocation would fail due to fragmentation
6. */
7. return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total)

在整合内存碎片的过程中,碎片页只会在本zone的内部移动,将位于zone低地址的页尽量移到zone的末端。申请新的页面位置通过compaction_alloc函数实现。

移动过程又分为同步和异步,内存申请失败后第一次compact将会使用异步,后续reclaim之后将会使用同步。同步过程只移动当面未被使用的页,异步过程将遍历并等待所有MOVABLE的页使用完成后进行移动。

2 按可移动性组织页

按照可移动性将内存页分为以下三个类型:
UNMOVABLE:在内存中位置固定,不能随意移动。kernel分配的内存基本属于这个类型;
RECLAIMABLE:不能移动,但可以删除回收。例如文件映射内存;
MOVABLE:可以随意移动,用户空间的内存基本属于这个类型。
申请内存时,根据可移动性,首先在指定类型的空闲页中申请内存,每个zone的空闲内存组织方式如下:

1. struct zone {
2. ......
3. struct free_area free_area[MAX_ORDER];
4. ......
5. }
6.  
7. struct free_area {
8. struct list_head free_list[MIGRATE_TYPES];
9. unsigned long nr_free;
10. };

当在指定类型的free_area申请不到内存时,可以从备用类型挪用,挪用之后的内存就会释放到新指定的类型列表中,kernel把这个过程称为“盗用”。
备用类型优先级列表如下定义:

1. static int fallbacks[MIGRATE_TYPES][4] = {
2. [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
3. [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
4. \#ifdef CONFIG_CMA
5. [MIGRATE_MOVABLE] = { MIGRATE_CMA, MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
6. [MIGRATE_CMA] = { MIGRATE_RESERVE }, /* Never used */
7. \#else
8. [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
9. \#endif
10. [MIGRATE_RESERVE] = { MIGRATE_RESERVE }, /* Never used */
11. \#ifdef CONFIG_MEMORY_ISOLATION
12. [MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
13. \#endif
14. };

值得注意的是并不是所有场景都适合按可移动性组织页,当内存大小不足以分配到各种类型时,就不适合启用可移动性。有个全局变量来表示是否启用,在内存初始化时设置:

DeepL Write
DeepL Write

DeepL推出的AI驱动的写作助手,在几秒钟内完善你的写作

下载
1. void __ref build_all_zonelists(pg_data_t *pgdat, struct zone *zone)
2. {
3. ......
4. if (vm_total_pages else
7. page_group_by_mobility_disabled = 0;
8. ......
9. }

如果page_group_by_mobility_disabled,则所有内存都是不可移动的。
其中有个参数决定了每个内存区域至少拥有的页,pageblock_nr_pages,它的定义如下:

#define pageblock_order HUGETLB_PAGE_ORDER

1. \#else /* CONFIG_HUGETLB_PAGE */
2. /* If huge pages are not used, group by MAX_ORDER_NR_PAGES */
3. \#define pageblock_order (MAX_ORDER-1)
4. \#endif /* CONFIG_HUGETLB_PAGE */
5. \#define pageblock_nr_pages (1UL 

在系统初始化期间,所有页都被标记为MOVABLE:

1. void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
2. unsigned long start_pfn, enum memmap_context context)
3. {
4. ......
5. if ((z->zone_start_pfn 

其它可移动性类型的页都是后来产生的,也就是前面说的“盗取”。在这种情况发生时,通常会“盗取”fallback中更高优先级、更大块连续的页,从而避免小碎片的产生。

1. /* Remove an element from the buddy allocator from the fallback list */
2. static inline struct page *
3. __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
4. {
5. ......
6. /* Find the largest possible block of pages in the other list */
7. for (current_order = MAX_ORDER-1; current_order >= order;
8. --current_order) {
9. for (i = 0;; i++) {
10. migratetype = fallbacks[start_migratetype][i];
11. ......
12. }

可以通过/proc/pageteypeinfo查看当前系统各种类型的页分布。

3 虚拟可移动内存域

在依据可移动性组织页的技术之前,还有一个方法已经合入kernel,那就是虚拟内存域:ZONE_MOVABLE。基本思想很简单:把内存分为两部分,可移动的和不可移动的。

1. enum zone_type {
2. \#ifdef CONFIG_ZONE_DMA
3. ZONE_DMA,
4. \#endif
5. \#ifdef CONFIG_ZONE_DMA32
6. ZONE_DMA32,
7. \#endif
8. ZONE_NORMAL,
9. \#ifdef CONFIG_HIGHMEM
10. ZONE_HIGHMEM,
11. \#endif
12. ZONE_MOVABLE,
13. __MAX_NR_ZONES
14. };

ZONE_MOVABLE的启用需要指定kernel参数kernelcore或者movablecore,kernelcore用来指定不可移动的内存数量,movablecore指定可移动的内存大小,如果两个都指定,取不可移动内存数量较大的一个。如果都不指定,则不启动。
与其它内存域不同的是ZONE_MOVABLE不关联任何物理内存范围,该域的内存取自高端内存域或者普通内存域。
find_zone_movable_pfns_for_nodes用来计算每个node中ZONE_MOVABLE的内存数量,采用的内存区域通常是每个node的最高内存域,在函数find_usable_zone_for_movable中体现。
在对每个node分配ZONE_MOVABLE内存时,kernelcore会被平均分配到各个Node:
kernelcore_node = required_kernelcore / usable_nodes;
在kernel alloc page时,如果gfp_flag同时指定了__GFP_HIGHMEM和__GFP_MOVABLE,则会从ZONE_MOVABLE内存域申请内存。

总之,Linux kernel内存碎片防治技术是一个非常重要的概念,可以帮助你更好地理解Linux系统中的内存管理。如果你想了解更多关于这个概念的信息,可以查看本文提供的参考资料。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

108

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

337

2023.10.11

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1373

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

705

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

295

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

778

2023.07.05

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

31

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.8万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号