首页 > 系统相关 >【内存管理】内存布局

【内存管理】内存布局

时间:2024-06-10 13:46:10浏览次数:16  
标签:kB 映射 管理 布局 Private 内存 Shared Dirty

ARM32位系统的内存布局图

32位操作系统的内存布局很经典,很多书籍都是以32位系统为例子去讲解的。32位的系统可访问的地址空间为4GB,用户空间为1GB ~ 3GB,内核空间为3GB ~ 4GB。

为什么要划分为用户空间和内核空间呢?

一般处理器会把运行模式分为好几个,比如x86分为rang0 ~ rang3级别。ARMv7架构中,又分为好几个模式,比如svc模式是给内核用的,usr模式是给用户态使用的。

当一个进程执行系统调用时,会陷入到内核态中,这个时候运行模式就从usr模式转换为svc模式,这就是我们常说的内核态。处于内核态的进程是可以访问内核空间的。所以就根据CPU的运行模式划分了两个空间。

我们先看下1GB的内核空间是怎么划分的,32位的系统中,通常配置的物理内存通常是大于1GB的,所以物理内存会划分为两部分,低端内存称为线性映射区,高端内存称为高端映射区。那这个分界线是怎么计算的呢,在ARM32中,分界线为760M。低端内存会做一比一映射到3GB ~ 3GB+760M。

这里讲的线性映射就是直接把物理内存的地址映射到线性映射区中,假设物理内存的DDR起始地址是0,映射的时候就有一个偏移量,这个偏移量就是0XC0000000,page offset。线性映射的地址我们就可以很方便的完成虚拟地址到物理地址的转换,只需要加减一个offset就可以。

高端内存的映射就没有线性映射那么简单了,使用高端内存时需要完成动态映射。

我们先看下1GB的内核空间剩下都做什么使用了。

  • vmalloc区域:分配的内存在虚拟地址是连续的,物理页面可以是离散的。vmalloc大概占用了200M物理内存。

  • fixmap:Fix map中的fix指的是固定的意思,那么固定什么东西呢?其实就是虚拟地址是固定的,也就是说,有些虚拟地址在编译(compile-time)的时候就固定下来了,而这些虚拟地址对应的物理地址不是固定的,是在kernel启动过程中被确定的。

  • vector:vector区域用于映射CPU vector page,大小一页4KB,从0xffff0000 - 0xffff1000。

接下来看下3GB用户空间的划分方式,一个进程要运行起来,必然要有自己的代码段和数据段,这部分在加载的时候就会被映射到虚拟地址。

  • 堆空间:从进程的开始到1GB的这部分我们称为堆空间,这部分主要是给malloc使用的。

  • mmap空间:1GB到3GB这部分是给mmap空间使用的,mmap可以用来映射文件也可以映射匿名页面。通常用户态分配大段内存的时候,Linux通常会使用mmap来完成分配。

从进程的角度看内存布局

readelf 查看程序段

接下来,我们通过一个C语言程序学习下内存布局,这个例子很简单,用malloc函数分配了内存内存,然后使用memset将该区域清零。

使用gcc编译为elf后,可以使用readelf 查看该程序包含那些段。

#include <stdio.h>
#include <string.h> 
#include <stdlib.h>

#define SIZE (100 * 1024)
void main()
{
    char* buf = malloc(SIZE);
    memset(buf, 0x58, SIZE);
    while(1)
        sleep(10000);
}
gcc -static  memory_process.c -o memory_process.elf

我们知道,通常Linux中流行的可执行文件的格式就是elf。使用gcc编译的elf就是我们讲的elf文件,目标文件除了包含了编译后的机器指令代码,还包含其他链接信息,比如符号表,调试信息,字符串等,通常这些信息会根据不同的属性存放在不同的段(section)中,这里我们只关注常见的段 。

  • .init:程序初始化的代码段。

  • .text:代码段,程序编译完后的机器指令。

  • .data:初始化过的全局的静态变量,还有一些局部的静态变量。

  • .rodata:只读变量,字符串,常量等。

  • .bss:未初始化的全局变量以及初始化为零的变量。

readelf 查看程序头

使用-l参数读下程序头(program header),它是用来描述OS是如何被映射到进程的虚拟地址空间的。

之前我们看到的30个段,在这里分成了7个族,并且显示每个族都包含那些段,这里我们只关注叫load的族,其他族主要是在程序装载的时候起到辅助作用。

第一个族里面包含init,text段,他的执行权限是只读,可执行的(RE)。起始地址0x0000000000400000,大小是0x00000000000b5986

另外一个族主要包含data和bss段,他的执行权限是可读写(RW)。起始地址0x00000000006b6120,大小是0x00000000000051b8

进程映射的过程

  1. 地址:本段在虚拟内存中的地址范围;对应vm_area_struct中的vm_startvm_end

  2. 权限:本段的权限; r-读,w-写,x-执行, p-私有;对应vm_flags。

  3. 偏移地址:即本段映射地址在文件中的偏移;对于有名映射指本段映射地址在文件中的偏移,对应vm_pgoff;对于匿名映射为vm_area_struct->vm_start

  4. 主设备号与次设备号:所映射的文件所属设备的设备号,对应vm_file->f_dentry->d_inode->i_sb->s_dev。匿名映射为0。其中fd为主设备号,00为次设备号。

  5. 文件索引节点号:对应vm_file->f_dentry->d_inode->i_ino,与ls –i显示的内容相符。匿名映射为0。

  6. 映射的文件名:对有名映射而言,是映射的文件名,对匿名映射来说,是此段内存在进程中的作用。[stack]表示本段内存作为栈来使用,[heap]作为堆来使用,其他情况则为无。

smaps 可以查看更多的内容

➜  example cat /proc/5823/smaps  
00400000-004b6000 r-xp 00000000 08:01 2319863                            /home/zhongyi/code/example/memory_process.elf
Size:                728 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                 640 kB
Pss:                 640 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:       640 kB
Private_Dirty:         0 kB
Referenced:          640 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd ex mr mw me dw sd 
006b6000-006bc000 rw-p 000b6000 08:01 2319863                            /home/zhongyi/code/example/memory_process.elf
Size:                 24 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                  24 kB
Pss:                  24 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         8 kB
Private_Dirty:        16 kB
Referenced:           24 kB
Anonymous:            16 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd wr mr mw me dw ac sd 
006bc000-006bd000 rw-p 00000000 00:00 0 
Size:                  4 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Anonymous:             4 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd wr mr mw me ac sd 
010cc000-010ef000 rw-p 00000000 00:00 0                                  [heap]
Size:                140 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                 108 kB
Pss:                 108 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:       108 kB
Referenced:          108 kB
Anonymous:           108 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd wr mr mw me ac sd 
7ffd5e0db000-7ffd5e0fc000 rw-p 00000000 00:00 0                          [stack]
Size:                132 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                  16 kB
Pss:                  16 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:        16 kB
Referenced:           16 kB
Anonymous:            16 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd wr mr mw me gd ac 
7ffd5e100000-7ffd5e103000 r--p 00000000 00:00 0                          [vvar]
Size:                 12 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd mr pf io de dd sd 
7ffd5e103000-7ffd5e105000 r-xp 00000000 00:00 0                          [vdso]
Size:                  8 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   0 kB
Shared_Clean:          4 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd ex mr mw me de sd 
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
Size:                  4 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: ex 

堆里面,匿名页面分配了108个物理内存,但我们的测试程序只分配了100k物理内存,这里匿名页面比分配的要大,这是因为进程在装载的时候也要消耗一些匿名页面。

010cc000-010ef000 rw-p 00000000 00:00 0                                  [heap]
Size:                140 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                 108 kB
Pss:                 108 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:       108 kB
Referenced:          108 kB
Anonymous:           108 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
THPeligible:            0
VmFlags: rd wr mr mw me ac sd 

根据以上信息,可以绘制出测试程序内存的布局图。

测试程序进程的elf这里只列出了常用的段。代码段的VMA属于page cache映射,这里把init段,text段,rodata段分为一个族,因为他们具有相同的权限,在进程加载的时候,会映射到代码段的VMA中。

数据段的VMA属于匿名映射,bss,data段具有相同的权限,在OS加载时,会映射到数据段的VMA中。

从数据段开始的地方就属于堆空间,我们在程序中用malloc分配了100K空间,这100K大小,也是在堆空间有对应的位置存在。

另外就是栈的VMA,进程有属于自己的VMA的栈。

以上就介绍了进程的ELF如何和进程的地址空间映射起来的。

64位系统的布局图

64位系统可以访问的空间就变得很大了。不过是ARM还是X86,实际的物理地址都不会用到64根地址线,通常是使用了48根地址线。而且,划分的用户空间和内核空间都是非常大的。

大家可以看这张图,把空间分为了三部分,一部分是内核空间,一部分是非规范区域(大家都不使用的),最后是用户空间。

  1. 用户空间:0x0000_0000_0000_0000到0x0000_ffff_ffff_ffff,一共有256TB。

  2. 非规范区域

  3. 内核空间:0xffff_0000_0000_0000到0xffff_ffff_ffff_ffff。一共有256TB。

内核空间又做了如下细分:

  • vmalloc区域:vmalloc函数使用的虚拟地址空间,kernel image也在vmalloc区域,内核镜像的起始地址 = KIMAGE_ADDR + TEXT_OFFSET, TEXT_OFFSET是内存中的内核镜像相对内存起始位置的偏移。

  • vmemmap区域:内存的物理地址如果不连续的话,就会存在内存空洞(稀疏内存),vmemmap就用来存放稀疏内存的page结构体的数据的虚拟地址空间。

  • PCI I/O区域:pci设备的I/O地址空间

  • Modules区域:内核模块使用的虚拟地址空间

  • normal memory线性映射区:范围是【0xffff_8000_0000_0000, 0xffff_ffff_ffff_ffff】, 一共有128TB, 但这里代码对应的是memblock_start_of_DRAM()memblock_end_of_DRAM()函数。
    memory根据实际物理内存大小做了限制,所以memroy显示了实际能够访问的内存区。

    MLM(__phys_to_virt(memblock_start_of_DRAM()), (unsigned long)high_memory))
    high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
    

    最终是通过dts或acpi中配置的memory节点确定的。

标签:kB,映射,管理,布局,Private,内存,Shared,Dirty
From: https://www.cnblogs.com/dongxb/p/18240613

相关文章

  • springboot高校运动会信息管理系统设计与实现-计算机毕业设计源码92968
    摘 要本论文介绍了一个高校运动会信息管理系统的设计和实现过程。首先是高校运动会的需求分析和可行性分析,通过比较运动会的各个工作流程,确定了系统的数据流程和数据库结构,然后介绍了高校运动会信息管理系统开发所使用的软件开发工具,最后描述了系统的详细设计与实现。本系统......
  • 【转载】ARM嵌入式系统为什么要做内存对齐
    做嵌入式系统软件开发,经常在代码中看到各种各样的对齐,很多时候我们都是知其然不知其所以然,知道要做好各种对齐,但是不明白为什么要对齐,不对齐会有哪些后果,这篇文章大概总结了内存对齐的理由。CPU体系结构和MMU的要求目前有一些RISC指令集的CPU不支持非对齐的内存变量访问操作,比......
  • 内存和磁盘设计
    内存设计根据之前论文之中所写,我们在内存中需要存储一份key所对应value的映射位置便于以后读出,在内存中存储的数据结构有许多,例如hash、跳表和btree等。 在教程中我们使用的是btree便于以后很方便的遍历key。数据结构的话直接拿现成的包直接用就行了btree库:https://github.......
  • 深入理解 C++ 动态内存管理:new vs malloc
    概述new/delete 是C++的关键字,需要编译器支持。malloc/free 是库函数,需要头文件支持。使用 new 申请内存分配时无需指定内存块大小,编译器会自动计算。而 malloc 需要明确指定所需内存的大小。new 会返回对象类型的指针,类型安全。而 malloc 返回 void*,需要进行强制......
  • [转帖]企业如何做好SQL质量的管理?
    点击标题下「蓝色微信名」可快速关注SQL操作数据库对应软件研发人员是一类基础且常见的工作内容,无论是日常的数据库应用开发,还是配合数据库产品迁移的应用改造,数据库设计和SQL的质量都是值得关注的问题。目前业界有很多提供SQL质量管理的产品,甲方也会有很多自研实现相关功......
  • 避免 OOMKilled:在 Kubernetes 环境中优化 Java 进程的内存配置
    避免OOMKilled:在Kubernetes环境中优化Java进程的内存配置DevOps云学堂译 奇妙的Linux世界 2024-06-1009:53 重庆 听全文公众号关注 「奇妙的Linux世界」设为「星标」,每天带你玩转Linux! 管理KubernetesPod中运行的Java进程的内存使用情况比人们想象......
  • 基于SpringBoot+Vue的项目申报管理系统(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 基于SpringBoot+Vue的小型医院医疗设备管理系统(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 第2讲:进程管理
    本文的主要内容:一个进程从生到死的过程。一、任务队列和task_struct任务描述符Linux的“任务队列”是一个双向链表,链表中每一项为进程描述符task_struct,它包含了一个正在执行的程序的完整信息:它打开的文件、进程的地址空间、挂起的信号、进程的状态等等。Linux通过slab分......
  • C++Primer Plus 第12章 类和动态内存分配 12.10编程练习第1题new,delete的指向深度拷
    C++PrimerPlus第12章类和动态内存分配12.10编程练习第1题`提示:练习一定要动手操作涉及标准函数及关键词1,new[],delete[],strlen(),strcpy_s(),cout,endl,explicit例如:1,对于下面的类的声明:`提示:设计数组和字符串的new,delete文章目录C++PrimerPlus第12章类......