Linux内核中的内存管理详解

张开发
2026/4/10 0:53:36 15 分钟阅读

分享文章

Linux内核中的内存管理详解
Linux内核中的内存管理详解引言内存管理是Linux内核中最核心、最复杂的组件之一它负责管理系统的物理内存为进程提供虚拟地址空间确保内存资源的高效利用和系统的稳定性。Linux内核的内存管理支持多种特性包括虚拟内存、分页、交换、缓存等同时提供了丰富的内存分配机制如slab分配器、伙伴系统等。本文将深入探讨Linux内核中的内存管理包括其设计原理、架构、核心机制和应用场景。内存管理的基本概念1. 物理内存与虚拟内存物理内存计算机中实际的RAM随机存取存储器虚拟内存操作系统为每个进程提供的独立地址空间虚拟地址进程使用的地址物理地址物理内存的实际地址2. 地址空间用户空间进程可以访问的地址空间内核空间内核专用的地址空间32位系统地址空间4GB用户空间3GB内核空间1GB64位系统地址空间更大用户空间和内核空间的分配更加灵活3. 分页机制页内存管理的基本单位通常是4KB页表记录虚拟页到物理页的映射页表项页表中的条目记录映射信息页目录多级页表结构中的上一级虚拟内存管理1. 地址空间布局// 32位系统地址空间布局// 0x00000000 - 0xBFFFFFFF用户空间3GB// 0xC0000000 - 0xFFFFFFFF内核空间1GB// 64位系统地址空间布局x86_64// 0x0000000000000000 - 0x00007FFFFFFFFFFF用户空间// 0xFFFF800000000000 - 0xFFFFFFFFFFFFFFFF内核空间2. 内存描述符mm_struct结构体描述进程的地址空间。structmm_struct{structvm_area_struct*mmap;structrb_rootmm_rb;structvm_area_struct*mmap_cache;unsignedlong(*get_unmapped_area)(structfile*filp,unsignedlongaddr,unsignedlonglen,unsignedlongpgoff,unsignedlongflags);void(*unmap_area)(structmm_struct*mm,unsignedlongaddr);unsignedlongmmap_base;unsignedlongmmap_legacy_base;unsignedlongtask_size;unsignedlonghighest_vm_end;pgd_t*pgd;atomic_tmm_users;atomic_tmm_count;intmap_count;spinlock_tpage_table_lock;structrw_semaphoremmap_sem;// 其他字段...};3. 虚拟内存区域vm_area_struct结构体描述进程的虚拟内存区域。structvm_area_struct{structmm_struct*vm_mm;unsignedlongvm_start;unsignedlongvm_end;structvm_area_struct*vm_next,*vm_prev;pgprot_tvm_page_prot;unsignedlongvm_flags;structrb_nodevm_rb;// 其他字段...};页表管理1. 页表结构Linux使用多级页表来管理虚拟地址到物理地址的映射。// 4级页表x86_64// PGDPage Global Directory// PUDPage Upper Directory// PMDPage Middle Directory// PTEPage Table Entry2. 页表操作// 设置页表项set_pte(pte_t*ptep,pte_tpte);// 清除页表项pte_clear(structmm_struct*mm,unsignedlongaddr,pte_t*ptep);// 检查页表项是否存在pte_present(pte_tpte);3. TLB转换后援缓冲器TLB是一种硬件缓存用于加速虚拟地址到物理地址的转换。// 刷新TLBflush_tlb_all();flush_tlb_mm(structmm_struct*mm);flush_tlb_page(structvm_area_struct*vma,unsignedlongpage);物理内存管理1. 页帧物理内存被分成固定大小的页帧通常是4KB。structpage{unsignedlongflags;atomic_t_count;atomic_t_mapcount;unsignedlongprivate;structaddress_space*mapping;pgoff_tindex;structlist_headlru;// 其他字段...};2. 伙伴系统伙伴系统用于管理物理页帧的分配和释放。// 分配页structpage*alloc_pages(gfp_tgfp_mask,unsignedintorder);// 分配单页structpage*alloc_page(gfp_tgfp_mask);// 释放页void__free_pages(structpage*page,unsignedintorder);3. 内存节点与区域Linux将物理内存分成多个节点和区域。// 内存节点typedefstructpglist_data{structzonenode_zones[MAX_NR_ZONES];structzonelistnode_zonelists[MAX_ZONELISTS];intnr_zones;// 其他字段...}pg_data_t;// 内存区域structzone{unsignedlongwatermark[NR_WMARK];unsignedlonglowmem_reserve[MAX_NR_ZONES];structper_cpu_pageset__percpu*pageset;spinlock_tlock;// 其他字段...};内存分配1. 页分配// 分配页structpage*alloc_pages(gfp_tgfp_mask,unsignedintorder);// 分配单页structpage*alloc_page(gfp_tgfp_mask);// 获取页的虚拟地址void*page_address(structpage*page);// 释放页void__free_pages(structpage*page,unsignedintorder);2. kmallockmalloc用于分配小块内存大小通常不超过页大小。#includelinux/slab.h// 分配内存void*kmalloc(size_tsize,gfp_tflags);// 释放内存voidkfree(constvoid*objp);3. vmallocvmalloc用于分配大块内存可以分配多个连续的虚拟页。#includelinux/vmalloc.h// 分配内存void*vmalloc(unsignedlongsize);// 释放内存voidvfree(constvoid*addr);4. gfp标志// 常用gfp标志GFP_KERNEL// 普通内核内存分配GFP_ATOMIC// 原子内存分配不能睡眠GFP_USER// 用户内存分配GFP_HIGHUSER// 高端内存分配GFP_DMA// DMA内存分配Slab分配器1. Slab的概念Slab分配器是Linux内核中用于管理小块内存分配的机制它预分配一些内存块然后从这些内存块中分配给需要的对象。2. 创建Slab缓存#includelinux/slab.h// 创建slab缓存structkmem_cache*kmem_cache_create(constchar*name,size_tsize,size_talign,unsignedlongflags,void(*ctor)(void*));// 销毁slab缓存voidkmem_cache_destroy(structkmem_cache*cachep);3. 从Slab缓存分配对象// 分配对象void*kmem_cache_alloc(structkmem_cache*cachep,gfp_tflags);// 释放对象voidkmem_cache_free(structkmem_cache*cachep,void*objp);页面缓存1. 页面缓存的概念页面缓存是Linux内核中用于缓存文件数据的机制它将文件数据缓存在内存中提高文件访问速度。2. address_spaceaddress_space结构体管理文件的页面缓存。structaddress_space{structinode*host;structradix_tree_rootpage_tree;spinlock_ttree_lock;unsignedinti_mmap_writable;structprio_tree_rooti_mmap;structlist_headi_mmap_nonlinear;spinlock_ti_mmap_lock;atomic_ttruncate_count;// 其他字段...};3. 页面缓存操作// 查找页面structpage*find_get_page(structaddress_space*mapping,pgoff_toffset);// 添加页面intadd_to_page_cache_locked(structpage*page,structaddress_space*mapping,pgoff_toffset,gfp_tgfp_mask);// 读取页面intread_cache_page(structaddress_space*mapping,pgoff_tindex,int(*filler)(void*,structpage*),void*data);交换Swapping1. 交换的概念交换是Linux内核中用于将不常用的内存页写入磁盘以释放物理内存的机制。2. 交换空间交换空间是磁盘上的一块区域用于存储换出的内存页。# 创建交换文件ddif/dev/zeroof/swapfilebs1Mcount1024chmod600/swapfilemkswap/swapfileswapon/swapfile# 查看交换空间swapon-scat/proc/swaps3. 页面换出Linux使用LRU最近最少使用算法选择要换出的页面。// 页面回收inttry_to_free_pages(structzonelist*zonelist,intorder,gfp_tgfp_mask);实际案例分析案例使用kmalloc分配内存#includelinux/module.h#includelinux/kernel.h#includelinux/init.h#includelinux/slab.hstaticvoid*my_buffer;staticint__initmymem_init(void){// 分配内存my_bufferkmalloc(1024,GFP_KERNEL);if(!my_buffer){printk(KERN_ERRmymem: failed to allocate memory\n);return-ENOMEM;}printk(KERN_INFOmymem: memory allocated at %p\n,my_buffer);return0;}staticvoid__exitmymem_exit(void){// 释放内存if(my_buffer){kfree(my_buffer);printk(KERN_INFOmymem: memory freed\n);}}module_init(mymem_init);module_exit(mymem_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(Your Name);MODULE_DESCRIPTION(kmalloc example);案例使用slab缓存#includelinux/module.h#includelinux/kernel.h#includelinux/init.h#includelinux/slab.hstructmy_struct{intdata1;chardata2[64];};staticstructkmem_cache*my_cache;staticstructmy_struct*my_obj;staticint__initmyslab_init(void){// 创建slab缓存my_cachekmem_cache_create(my_cache,sizeof(structmy_struct),0,SLAB_HWCACHE_ALIGN,NULL);if(!my_cache){printk(KERN_ERRmyslab: failed to create cache\n);return-ENOMEM;}// 分配对象my_objkmem_cache_alloc(my_cache,GFP_KERNEL);if(!my_obj){printk(KERN_ERRmyslab: failed to allocate object\n);kmem_cache_destroy(my_cache);return-ENOMEM;}// 使用对象my_obj-data142;strcpy(my_obj-data2,Hello, slab!);printk(KERN_INFOmyslab: object created, data1 %d, data2 %s\n,my_obj-data1,my_obj-data2);return0;}staticvoid__exitmyslab_exit(void){// 释放对象if(my_obj){kmem_cache_free(my_cache,my_obj);}// 销毁缓存if(my_cache){kmem_cache_destroy(my_cache);}printk(KERN_INFOmyslab: exit\n);}module_init(myslab_init);module_exit(myslab_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(Your Name);MODULE_DESCRIPTION(slab example);结论Linux内核的内存管理是一个功能强大、设计复杂的系统它为进程提供了虚拟地址空间管理着物理内存的分配和回收确保了内存资源的高效利用和系统的稳定性。通过深入了解Linux内存管理的架构、核心机制和实现原理我们可以更好地理解和优化内存使用提高系统的性能和可靠性。在实际应用中我们需要根据场景选择合适的内存分配方式合理设计内存使用方案避免内存泄漏和内存溢出。作为系统开发者和内核工程师掌握内存管理的知识是非常重要的它将帮助我们更好地设计和实现系统软件解决内存相关的问题提高系统的性能和稳定性。

更多文章