0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

内核内存布局

电子工程师 来源:嵌入式开发AIoT 作者:嵌入式开发AIoT 2022-08-08 17:14 次阅读

一、内核内存布局

64位Linux一般使用48位表示虚拟地址空间,43位表示物理地址,通过命令:cat /proc/cpuinfo

32401ca6-16c0-11ed-ba43-dac502259ad0.png
  • ARM64架构处理器采用48位物理寻址机制,最大可寻找256TB的物理地址空间。对于 目前应用完全足够,不需要扩展到64位的物理寻址。虚拟地址也同样最大支持48位寻址,所以 在处理器架构设计上,把虚拟地址空间划分为两个空间,每个空间最大支持256TB,linux内核 在大多数体系结构上都把两个地址划分为:用户空间和内核空间。

  • 用户空间:0x0000_0000_0000_0000至0x0000_ffff_ffff_ffff;

  • 内核空间:0xffff_0000_0000_0000至0xffff_ffff_ffff_ffff;

QEMU平台,可以打印ARM64架构linux内核内存分布情况

327151a4-16c0-11ed-ba43-dac502259ad0.png

二、堆管理

堆是进程中主要用于动态分配变量和数据的内存区域,堆的管理对应程序员不是直接可见的。因为它依赖标准库提供的各个辅助函数(其中最重要的是malloc)来分配任意长度的内存区。malloc和内核之间的经典接口是brk系统调用,负责扩展/收缩堆。

329df57e-16c0-11ed-ba43-dac502259ad0.png
  • 堆是一个连续的内存区域,在扩展时自下至上增长。其中mm_struct结构,包含堆在虚拟地 址空间中的起始和当前结束地址(start_brk和brk)。
  • brk系统调用用于指定堆在虚拟地址空间中新的结束地址(如果堆将要收缩,当然可以小于当前值)。brk系统调用通过do_brk增长动态分配区(内核源码分mm/mmap.c)

三、sys_brk流程

  1. 检查资源限制;

  2. 将brk值对齐到页;

  3. 是否想增加brk值?(这个地方要结合源码看)

    是-->do_brk();返回新的brk的值;

    否-->do_munmap();返回新的brk的值;

brk机制不是一个独立的内核概念,而是基于匿名映射实现,以减少内部的开销。在检查过用brk的值的新地址未超出推的限制之后,sys_brk第一个重要操作是请求的地址按页长对齐。brk()用于进程向内核申请空间,用于扩展用户堆栈空间,或者回收堆栈空间。

  • malloc为小空间申请,brk()为大块空间申请。do_brk()用于增长动态分配区。do_munmap()释放动态分配区;
  • do_brk()源码分析:
staticunsignedlongdo_brk(unsignedlongaddr,unsignedlonglen)
{
structmm_struct*mm=current->mm;
structvm_area_struct*vma,*prev;
unsignedlongflags;
structrb_node**rb_link,*rb_parent;
pgoff_tpgoff=addr>>PAGE_SHIFT;
interror;

//首先对len这个长度进行页面对齐去判断页面对齐之后是否超出边界
len=PAGE_ALIGN(len);
if(!len)
returnaddr;

flags=VM_DATA_DEFAULT_FLAGS|VM_ACCOUNT|mm->def_flags;

//检查是否有足够内存空间来分析len大小的内存。判断虚拟地址空间是否足够
error=get_unmapped_area(NULL,addr,len,0,MAP_FIXED);
if(offset_in_page(error))
returnerror;

error=mlock_future_check(mm,mm->def_flags,len);
if(error)
returnerror;

/*
*mm->mmap_semisrequiredtoprotectagainstanotherthread
*changingthemappingsincasewesleep.
*/
verify_mm_writelocked(mm);

/*
*Clearoldmaps.thisalsodoessomeerrorcheckingforus
*/
//循环遍历用户进程红黑树中VMA,然后根据addr来查找合适的插入点
while(find_vma_links(mm,addr,addr+len,&prev,&rb_link,
&rb_parent)){
if(do_munmap(mm,addr,len))
return-ENOMEM;
}

/*Checkagainstaddressspacelimits*after*clearingoldmaps...*/
//检查是否要对此虚拟区间进行扩充
if(!may_expand_vm(mm,len>>PAGE_SHIFT))
return-ENOMEM;

if(mm->map_count>sysctl_max_map_count)
return-ENOMEM;
//判断系统是否有足够内存
if(security_vm_enough_memory_mm(mm,len>>PAGE_SHIFT))
return-ENOMEM;

/*Canwejustexpandanoldprivateanonymousmapping?*/
//判读是否可以合并,如果可以合并就合并成为一个vam区
vma=vma_merge(mm,prev,addr,addr+len,flags,
NULL,NULL,pgoff,NULL,NULL_VM_UFFD_CTX);

//如果能合并直接gotoout
if(vma)
gotoout;

/*
*createavmastructforananonymousmapping
*/

//如果没有办法合并,只有新创建一个VMA,VMA地址空间是【addr,addr+len】
vma=kmem_cache_zalloc(vm_area_cachep,GFP_KERNEL);
if(!vma){
vm_unacct_memory(len>>PAGE_SHIFT);
return-ENOMEM;
}

//指向匿名域指针
INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_mm=mm;//指向VMA所属于进程structmm_struct结构
vma->vm_start=addr;
vma->vm_end=addr+len;
vma->vm_pgoff=pgoff;
vma->vm_flags=flags;
vma->vm_page_prot=vm_get_page_prot(flags);
vma_link(mm,vma,prev,rb_link,rb_parent);
out://增加进程地址空间长度
perf_event_mmap(vma);
mm->total_vm+=len>>PAGE_SHIFT;
if(flags&VM_LOCKED)
mm->locked_vm+=(len>>PAGE_SHIFT);
vma->vm_flags|=VM_SOFTDIRTY;
returnaddr;
}

- END -


审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    18266

    浏览量

    222118
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39844
  • Linux
    +关注

    关注

    87

    文章

    10988

    浏览量

    206725
  • AIoT
    +关注

    关注

    8

    文章

    1259

    浏览量

    30051

原文标题:接上一篇续集

文章出处:【微信号:嵌入式开发AIoT,微信公众号:嵌入式开发AIoT】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    什么是HBM3E内存?Rambus HBM3E/3内存控制器内核

    Rambus HBM3E/3 内存控制器内核针对高带宽和低延迟进行了优化,以紧凑的外形和高能效的封装为人工智能训练提供了最大的性能和灵活性。
    发表于 03-20 14:12 529次阅读
    什么是HBM3E<b class='flag-5'>内存</b>?Rambus HBM3E/3<b class='flag-5'>内存</b>控制器<b class='flag-5'>内核</b>

    Linux内核内存管理之内核非连续物理内存分配

    的主要优点是避免了外部碎片,而缺点是需要修改内核页表。显然,非连续内存区域的大小必须是4096的倍数。Linux使用非连续物理内存区的场景有几种:(1)为swap区分配数据结构;(2)为模块分配空间
    的头像 发表于 02-23 09:44 375次阅读
    Linux<b class='flag-5'>内核</b><b class='flag-5'>内存</b>管理之<b class='flag-5'>内核</b>非连续物理<b class='flag-5'>内存</b>分配

    Linux内核内存管理之ZONE内存分配器

    内核中使用ZONE分配器满足内存分配请求。该分配器必须具有足够的空闲页帧,以便满足各种内存大小请求。
    的头像 发表于 02-21 09:29 413次阅读

    Linux内核内存管理架构解析

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等,而且对性能也有很高
    的头像 发表于 01-04 09:24 317次阅读
    Linux<b class='flag-5'>内核</b><b class='flag-5'>内存</b>管理架构解析

    Linux内核内存规整总结

    1.前言 伙伴系统作为内核最基础的物理页内存分配器,具有高效、实现逻辑简介等优点,其原理页也尽可能降低内存外部碎片产生,但依然无法杜绝碎片问题。外部碎片带来的最大影响就是内存足够,但是
    的头像 发表于 11-11 11:17 929次阅读
    Linux<b class='flag-5'>内核</b><b class='flag-5'>内存</b>规整总结

    内存内核中发生页面迁移的典型场景

    页面迁移(page migrate)最早是为 NUMA 系统提供一种将进程页面迁移到指定内存节点的能力用来提升访问性能。后来在内核中广泛被使用,如内存规整、CMA、内存hotplug等
    的头像 发表于 11-08 12:28 309次阅读
    <b class='flag-5'>内存</b><b class='flag-5'>内核</b>中发生页面迁移的典型场景

    浅聊Rust程序内存布局

    内存布局看似是底层和距离应用程序开发比较遥远的概念集合,但其对前端应用的功能实现颇具现实意义。从WASM业务模块至Nodejs N-API插件,无处不涉及到FFI跨语言互操作。甚至,做个文本
    的头像 发表于 11-01 16:44 351次阅读
    浅聊Rust程序<b class='flag-5'>内存</b><b class='flag-5'>布局</b>

    内存布局图角度看内存管理

    我们知道Linux是分为两种状态 用户态和内核态,Linux内核需要跑在硬件平台上,硬件平台也有自己的状态。这里还是ARM,ARM有其中处理器的模式。 用户模式(user):用户程序运行的模式。系统
    的头像 发表于 10-30 17:50 324次阅读

    U54内核上CLINT的内存映射

    ) {// handler code} 此属性将保存和恢复处理程序中使用的寄存器,并在处理程序的末尾插入一条 mret 指令。 CLINT内存映射 下图是U54 内核上 CLINT 的内存映射: 注意
    的头像 发表于 10-08 09:34 274次阅读
    U54<b class='flag-5'>内核</b>上CLINT的<b class='flag-5'>内存</b>映射

    Linux内核内存管理详解

    内存管理的主要工作就是对物理内存进行组织,然后对物理内存的分配和回收。但是Linux引入了虚拟地址的概念。
    发表于 08-31 14:46 425次阅读
    Linux<b class='flag-5'>内核</b>的<b class='flag-5'>内存</b>管理详解

    C语言中数组和结构体的内存表示和布局

    C语言中,数组和结构体都可以代表一块内存,但为什么结构体可以直接赋值,而数组不可以?这个问题涉及到C语言的设计哲学、语法规则以及内存布局的细节。本文将深入探讨这些问题,通过原理介绍和举例说明来解释为什么数组和结构体在赋值操作上有
    发表于 08-28 10:54 469次阅读

    Linux内存相关知识科普

    Linux 内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍**Linu****x 内存组织结构和页面布局
    发表于 07-25 14:43 548次阅读
    Linux<b class='flag-5'>内存</b>相关知识科普

    详解Java虚拟机的JVM内存布局

    JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的稳定高效运行。不同的JVM对于内存的划分方式和管理机制存在部分差异。结合JVM虚拟机规范,一起来探讨j
    的头像 发表于 07-13 09:52 317次阅读
    详解Java虚拟机的JVM<b class='flag-5'>内存</b><b class='flag-5'>布局</b>

    Linux内核内存泄漏怎么办

    在Linux内核开发中,Kmemleak是一种用于检测内核内存泄漏的工具。
    发表于 07-04 11:04 591次阅读

    Linux内核实现内存管理的基本概念

    本文概述Linux内核实现内存管理的基本概念,在了解基本概念后,逐步展开介绍实现内存管理的相关技术,后面会分多篇进行介绍。
    发表于 06-23 11:56 522次阅读
    Linux<b class='flag-5'>内核</b>实现<b class='flag-5'>内存</b>管理的基本概念