Linux kernel内存碎片防治技术:深入理解内存管理
你是否曾经遇到过在Linux系统中出现的各种内存问题?比如内存泄漏、内存碎片等等。这些问题都可以通过深入理解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. };
值得注意的是并不是所有场景都适合按可移动性组织页,当内存大小不足以分配到各种类型时,就不适合启用可移动性。有个全局变量来表示是否启用,在内存初始化时设置:
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系统中的内存管理。如果你想了解更多关于这个概念的信息,可以查看本文提供的参考资料。
以上是Linux kernel内存碎片防治技术:深入理解内存管理的详细内容。更多信息请关注PHP中文网其他相关文章!

Linux和Windows的安全模型各有优势。Linux提供灵活性和可定制性,通过用户权限、文件系统权限和SELinux/AppArmor实现安全。Windows则注重用户友好性,依赖WindowsDefender、UAC、防火墙和BitLocker保障安全。

Linux和Windows在硬件兼容性上不同:Windows有广泛的驱动程序支持,Linux依赖社区和厂商。解决Linux兼容性问题可通过手动编译驱动,如克隆RTL8188EU驱动仓库、编译和安装;Windows用户需管理驱动程序以优化性能。

Linux和Windows在虚拟化支持上的主要区别在于:1)Linux提供KVM和Xen,性能和灵活性突出,适合高定制环境;2)Windows通过Hyper-V支持虚拟化,界面友好,与Microsoft生态系统紧密集成,适合依赖Microsoft软件的企业。

Linux系统管理员的主要任务包括系统监控与性能调优、用户管理、软件包管理、安全管理与备份、故障排查与解决、性能优化与最佳实践。1.使用top、htop等工具监控系统性能,并进行调优。2.通过useradd等命令管理用户账户和权限。3.利用apt、yum管理软件包,确保系统更新和安全。4.配置防火墙、监控日志、进行数据备份以确保系统安全。5.通过日志分析和工具使用进行故障排查和解决。6.优化内核参数和应用配置,遵循最佳实践提升系统性能和稳定性。

学习Linux并不难。1.Linux是一个开源操作系统,基于Unix,广泛应用于服务器、嵌入式系统和个人电脑。2.理解文件系统和权限管理是关键,文件系统是层次化的,权限包括读、写和执行。3.包管理系统如apt和dnf使得软件管理方便。4.进程管理通过ps和top命令实现。5.从基本命令如mkdir、cd、touch和nano开始学习,再尝试高级用法如shell脚本和文本处理。6.常见错误如权限问题可以通过sudo和chmod解决。7.性能优化建议包括使用htop监控资源、清理不必要文件和使用sy

Linux管理员的平均年薪在美国为75,000至95,000美元,欧洲为40,000至60,000欧元。提升薪资可以通过:1.持续学习新技术,如云计算和容器技术;2.积累项目经验并建立Portfolio;3.建立职业网络,拓展人脉。

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

互联网运行不依赖单一操作系统,但Linux在其中扮演重要角色。Linux广泛应用于服务器和网络设备,因其稳定性、安全性和可扩展性受欢迎。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3汉化版
中文版,非常好用

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),