内核内存布局

一、内核内存布局 64位linux一般使用48位表示虚拟地址空间,43位表示物理地址,通过命令:cat /proc/cpuinfo
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内核内存分布情况
二、堆管理 堆是进程中主要用于动态分配变量和数据的内存区域,堆的管理对应程序员不是直接可见的。因为它依赖标准库提供的各个辅助函数(其中最重要的是malloc)来分配任意长度的内存区。malloc和内核之间的经典接口是brk系统调用,负责扩展/收缩堆。
堆是一个连续的内存区域,在扩展时自下至上增长。其中mm_struct结构,包含堆在虚拟地 址空间中的起始和当前结束地址(start_brk和brk)。 brk系统调用用于指定堆在虚拟地址空间中新的结束地址(如果堆将要收缩,当然可以小于当前值)。brk系统调用通过do_brk增长动态分配区(内核源码分mm/mmap.c) 三、sys_brk流程 检查资源限制;
将brk值对齐到页;
是否想增加brk值?(这个地方要结合源码看)
是-->do_brk();返回新的brk的值;
否-->do_munmap();返回新的brk的值;
brk机制不是一个独立的内核概念,而是基于匿名映射实现,以减少内部的开销。在检查过用brk的值的新地址未超出推的限制之后,sys_brk第一个重要操作是请求的地址按页长对齐。brk()用于进程向内核申请空间,用于扩展用户堆栈空间,或者回收堆栈空间。
malloc为小空间申请,brk()为大块空间申请。do_brk()用于增长动态分配区。do_munmap()释放动态分配区; do_brk()源码分析: static unsigned long do_brk(unsigned long addr, unsigned long len){ struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev; unsigned long flags; struct rb_node **rb_link, *rb_parent; pgoff_t pgoff = addr >> page_shift; int error; // 首先对len这个长度进行页面对齐去判断页面对齐之后是否超出边界 len = page_align(len); if (!len)  return addr; 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))  return error; error = mlock_future_check(mm, mm->def_flags, len); if (error)  return error; /*  * mm->mmap_sem is required to protect against another thread  * changing the mappings in case we sleep.  */ verify_mm_writelocked(mm); /*  * clear old maps.  this also does some error checking for us  */  // 循环遍历用户进程红黑树中vma,然后根据addr来查找合适的插入点 while (find_vma_links(mm, addr, addr + len, &prev, &rb_link,         &rb_parent)) {  if (do_munmap(mm, addr, len))   return -enomem; } /* check against address space limits *after* clearing old maps... */    // 检查是否要对此虚拟区间进行扩充 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; /* can we just expand an old private anonymous mapping? */    // 判读是否可以合并,如果可以合并就合并成为一个vam区 vma = vma_merge(mm, prev, addr, addr + len, flags,   null, null, pgoff, null, null_vm_uffd_ctx);     // 如果能合并直接goto out    if (vma)  goto out; /*  * create a vma struct for an anonymous mapping  */        //如果没有办法合并,只有新创建一个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所属于进程struct mm_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; return addr;}  
- end -


美光昨天发布了最新款的5210 ION系列企业级SSD 也是全球首款QLC闪存产品
何谓电动汽车的「副作用」?
华为采用可证京东方的OLED面板技术已成功
PCBA焊接中焊点拉尖的产生和解决方法
MODEM的拨号方式
内核内存布局
白光LED驱动电路图
如何选择LED电子显示屏型号
谷景电感技术助力无人机行业升级换代
再谈“软件定义汽车”,剖析SOAFEE的成绩、打法和目标
中兴已与美国签署撤销7年禁购令初步协议 软银拟7.75亿美元出售ARM中国公司51%股权
中兴天机axonm怎么样 它的外观是配的上顶级二字的
vivo成立了数字金服中心,前网易金融总裁牵头
350种类型、10W+量级的API,企业应该怎么管?
红外对射和激光对射,哪个更好用?
开关磁阻电机调速系统的特点
电动汽车控制器专用薄膜电容
IPv6仅仅是比ipv4增加了地址长度吗
LED屏幕与OLED屏幕之间的区别不仅仅只是相差一个字母
SMT贴片加工厂验收电路板时都会检查哪些内容