文章目录 一、Linux 内核中对 " 虚拟地址空间 " 的描述 二、task_struct 结构体源码 一、Linux 内核中对 " 虚拟地址空间 " 的描述 ---- 进程 的 " 虚拟地址空间 "..." 进行描述 ; vm_area_struct 是 " 较高层次 " 上的描述 " 虚拟地址空间 " 的区间 的 ; 每个进程只有 1 个 mm_struct 结构体数据 , 用于描述 整个 "...结构体 , mm_struct 结构体中 , 有指针指向 vm_area_struct 结构体 ; 二、task_struct 结构体源码 ---- task_struct 进程描述符 结构体 , 定义在...Linux 内核源码的 linux-4.12\include\linux\sched.h#483 位置 ; task_struct 中的 mm active_mm 是 描述 " 整个虚拟空间 " mm_struct...信号处理相关字段 | 信号量和共享内存相关字段 )
由于 Linux 内核支持虚拟内存管理,物理内存碎片通常不是问题,因为在页表的帮助下,物理上分散的内存在虚拟地址空间仍然是连续的 (除非使用大页),但对于需要从内核线性映射区分配连续物理内存的需求来说就会变的非常困难...本文将重点描述当前常用的 3.10 版本内核在伙伴分配器的预防内存碎片的扩展,内存规整原理,如何查看碎片指数,以及如何量化内存规整带来的延迟开销等。...根据迁移类型进行分组 我们在了解迁移类型前,需要先理解内存地址空间布局,每一种处理器架构都有定义,比如 x86_64 的定义在 mm.txt。...对于通过页表访问虚拟地址空间的情况 (比如用户空间的堆内存需求)并不需要连续物理内存,为什么呢?...我在上一篇文章 我们为什么要禁用 THP 有提到可以用内核提供了 ftrace 事件来分析外部内存碎片事件,具体的步骤如下: echo 1 > /sys/kernel/debug/tracing/events
那你看看这段代码的输出,你觉得你的机器会有这么大的内存吗?...再参考linux内核文档的 5level-paging (在文章最后的参考资料中有具体网址),我们可以确切得知,4-level paging的有效虚拟地址是48位,有效物理地址是46位,5-level...我们还知道,在该地址空间内,不仅有我们的用户程序,还有内核代码(是的,内核代码也映射到了用户进程的虚拟地址空间)。...0x09 虚拟地址的意义 聊了这么多,那虚拟地址存在的意义是什么呢?为什么不直接使用物理地址呢? 好处非常多,我简单说几个吧。...比如共享相同的内核代码,以及共享库代码,这样这些共用的代码就只占用一份内存,他们会以映射到进程虚拟地址空间的方式,供用户进程使用。
首先看linux进程在32位处理器下的虚拟空间内存布局,以i386 32位机器为例 x86_32 32位处理器进程虚拟地址空间布局 每个用户进程的虚拟地址空间为...内核空间为0XC0000000—0xFFFFFFFF 1GB, 如果物理内存大于896MB,则内核的虚拟地址0xC0000000—0xF8000000 和 物理内存0—896MB对等映射。...所以内核 为了访问大于896MB的物理内存需要设置一段虚拟区域映射其他的物理内存,这段虚拟地址叫做高端内存,VMALLOC区用函数vmalloc分配内存页面不保证连续,持久映射用函数kmap建立映射,这段映射是长期映射...linux在x86_64下的经典布局如下图 x86_64 64位处理器进程地址空间布局 用户空间分区一致,区别就是地址空间变大了,内核空间取消了高端内存,因为内核空间的地址空间完全可以访问全部物理内存...下面以32位处理器为例看linux内核如何建立用户进程空间的内存布局的,fork调用是复制父进程的struct mm_struct的内存描述符不需要重新建立布局,而建立新的内存布局是通过加载二进制可执行文件
进程虚拟内存空间 虚拟地址空间分布 理论上,64bit地址支持访问的地址空间是[0, 2(64-1)],而实际上现有的应用程序都不会用这么大的地址空间,并且arm64芯片现在也不支持访问这么大的地址空间...,现在的移动设备显然用不到这么大的内存空间,所以大部分Android设备中CONFIG_ARM64_VA_BITS默认配置的是39,即64bit进程的最大虚拟地址空间大小是512GB。...进程在访问虚拟地址空间的任意合法地址时,都要按照逻辑地址->线性地址->物理地址的顺序换算才能找到对应的物理地址;由于段式内存管理存在性能、访问效率的问题,以及Linux要兼容各种CPU,在Linux内核中所有的用户态进程使用的同一个段...struct mm_struct 每个进程或内核线程都由一个任务描述数据结构(task_struct)来管理,每个task_struct中有个struct mm_strcut数据结构指针,用来管理任务的虚拟地址空间...传统布局 映射区域自底向上增长,mmap_base的值是TASK_UNMAPPED_BASE,ARM64架构中定义为TASK_SIZE/4。内核默认启用内存映射区域随机化,在该起始地址加上一个随机值。
一、内存管理架构 二、虚拟地址空间布局架构 三、物理内存体系架构 四、内存结构 五、内存模型 六、虚拟地址和物理地址的转换 七、内存映射原理分析 一、内存管理架构 内存管理子系统架构可以分为:用户空间、...二、虚拟地址空间布局架构 上面的用户空间和内核空间所指的都是虚拟地址,物理地址没有用户和内核之分。每个项目的物理地址对于进程不可见,谁也不能直接访问这个物理地址。操作系统会给进程分配一个虚拟地址。...所有进程共享内核虚拟地址空间,每个进程有独立的用户虚拟地址空间,同一个线程组的用户线程共享用户虚拟地址空间,内核线程没有用户虚拟地址空间。在程序里面,指令写入的地址是虚拟地址。...32位处理器使用32位虚拟地址,而64位处理器却不是使用64位虚拟地址。因为目前应用程序没有那么大的内存需求,所以ARM64和X86_64处理器不支持完全的64位虚拟地址,而是使用了48位。...这么大的虚拟空间一切二,一部分用来放内核的东西,称为内核空间,一部分用来放进程的东西,称为用户空间。
目前的内核的内存管理总是假定使用四级页表, 而不管底层处理器是否如此...., 详细的讲解了Linux内核分页机制的实现机制 3 Linux分页机制的演变 3.1 Linux的页表实现 由于程序存在局部化特征, 这意味着在特定的时间内只有部分内存会被频繁访问,具体点,进程空间中的...text段(即程序代码), 堆, 共享库,栈都是固定在进程空间的某个特定部分,这样导致进程空间其实是非常稀疏的, 于是,从硬件层面开始,页表的实现就是采用分级页表的方式,Linux内核当然也这么做。...至于这种做法为什么能节省内存,举个更简单的例子更容易明白。比如要记录16个球场的使用情况,每张纸能记录4个场地的情况。...在2004年10月,当时的X86_64架构代码的维护者Andi Kleen提交了一个叫做4level page tables for Linux的PATCH系列,为Linux内核带来了4级页表的支持。
Linux内核在启动时会打印出内核内存空间的布局图,下面是ARM Vexpress平台打印出来的内存空间布局图: ? 这部分信息打印是在mem_init()函数中实现的。...,接下来打包成二进制文件,该操作由arch/arm/kernel/vmlinux.ld.S控制,其中也划定了内核的内存布局。...这1GB的映射空间,其中有一部分用于直接映射物理地址。这个区域称为线性映射区。在ARM32平台上,物理地址[0:760MB]的这一部分内存被线性映射到[3GB:3GB+768MB]的虚拟地址上。...内核中有相关的宏来实现线性映射区虚拟地址与物理地址的查找过程,例如__pa(x)和__va(x) [arch/arm/include/asm/memory.h] #define __pa(x) __virt_to_phys...0x2F80_0000,即760MB; 为什么内核只线性映射760MB呢?
实际上所谓的进程虚拟地址空间本质上是一个内核数据结构(内似于PCB)。...这个内核数据结构叫做mm_struct,在PCB中有一个指针指向虚拟地址空间,PCB控制着这个虚拟地址空间,然后mm_struct通过映射,映射到真实的物理内存上。...页表 什么是页表: 页表是操作系统内核用来管理虚拟地址和物理地址之间映射的一个数据结构。它的核心作用是支持虚拟内存,使得每个进程可以在自己的独立虚拟地址空间中运行,增强了内存隔离和安全性。...简单了解完页表后,我们来解释一下我们刚刚的现象,为什么父进程的gval不变,子进程的gval在改变,两个gval都指向同一块空间。...掌握程序地址空间的布局不仅能帮助我们理解进程的内存使用,还能为调试、性能优化和内存管理打下坚实基础。
我们知道,这么大的虚拟地址空间,不可能都有真实内存对应,所以这里是映射的数目。当内存吃紧的时候,有些页可以换出到硬盘上,有的页因为比较重要,不能换出。...前面咱们讲 malloc 申请一大块内存的时候,就是通过 mmap 在这里映射一块区域到物理内存。咱们加载动态链接库 so 文件,也是在这个区域里面,映射一块区域到 so 文件。...内核态的虚拟空间和某一个进程没有关系,所有进程通过系统调用进入到内核之后,看到的虚拟地址空间都是一样的。在内核态,32 位和 64 位的布局差别比较大,主要是因为 32 位内核态空间太小了。...其实 64 位的内核布局反而简单,因为虚拟空间实在是太大了,根本不需要所谓的高端内存,因为内核是 128T,根本不可能有物理内存超过这个值。64 位的内核主要包含以下几个部分。...这里和直接映射区有点像,但是不矛盾,因为直接映射区之前有 8T 的空当区域,早就过了内核代码在物理内存中加载的位置。进程运行状态在 32 位下对应关系。对于 64 位的对应关系,只是稍有区别。
2、基本理解 由于硬盘中存在可执行的程序,当我们开始运行程序的时候,就会把代码和数据放在内存中,由前面所学到的一切的有关进程的知识之中,我们知道在操作系统中有着进程task_struct来帮助管理这些数据和代码以及别的一些状态...3、细节问题 3、1、独立性细节 独立性: 如果父子进程不写,未来一个全局变量是父子共享的,代码是共享的(只读的)。 1、问题: 为什么我们要这么做?...换句话说,为什么不是直接把所有的数据都拷贝到子进程之中呢?为什么是只有在修改变量的值的时候才创建新的内存空间?...1、答案: 那是因为在父进程中有很多的数据子进程不一定会修改,比如说命令行参数和环境变量,子进程几乎都不会进行修改,所以由于这部分的数据本来改动就不大,但是占据的数据却很大的话,每次还要单独拷贝一份放在内存空间中就会相当的消耗资源空间...除此之外,操作系统并不是说每一次的进程中malloc的时候都需要再内存空间中申请一块地址,只有在使用的时候才会真正的再物理内存中申请,在没开始使用的时候,只不过是在地址空间上申请,在页表中申请了虚拟地址
DMA_ZONE表示DMA可使用的内存范围,现在x86_64下一般设备所有内存都可用,所以说DMA_ZONE和bus_address为了兼容而保留其实不用特殊考虑。...内核态DMA驱动和DMA API 一般外设都自带DMA功能,DMA只是外设的数据传输通道,外设的功能各不一样,但DMA传输数据通道功能都一样,所以内核就有了DMA API,其它外设驱动只要调用内核DMA...API就可以搞定DMA相关的功能了,内存映射/数据对齐/缓存一致性等都由内核DMA API搞定。...第二个问题是怎么保证虚拟地址对应的物理地址一定存在于内存中并且固定在内存中的同一个物理地址,虚拟地址一定有对应的物理地址好说,可以直接把page的ref加1,并且强行给page写个0数据,但虚拟地址固定对应到一个物理地址就难说了...dpdk中有--iova ,相比较于qemu这儿就是小菜一碟。
那我们先了解下什么是虚拟地址空间:在 32 位机器下,虚拟地址空间大小为 4G。...虽然说内核和用户态进程占用了这么大地址空间,但是并不意味它们使用了这么多物理内存,仅表示它可以支配这么大的地址空间。它们是根据需要,将物理内存映射到虚拟地址空间中使用。...Linux 对进程地址空间有个标准布局,地址空间中由各个不同的内存段组成 (Memory Segment),主要的内存段如下: 程序段 (Text Segment):可执行文件代码的内存映射 数据段 (...,那我们看下 Linux 内核中是怎么体现上面内存布局的。...Linux 为什么需要区分这些栈? 为什么需要区分这些栈,其实都是设计上的问题。这里就我看到过的一些观点进行汇总,供大家讨论: 1. 为什么需要单独的进程内核栈?
虚拟地址空间是指进程在内存中使用的地址范围。 当 legacy_va_layout 参数被设置为1时,Linux 内核使用传统的虚拟地址布局方式。...当 legacy_va_layout 参数被设置为0时,Linux 内核使用新的虚拟地址布局方式。在这种布局方式下,内核将虚拟地址空间的前1TB保留给用户空间,将接下来的128TB保留给核心空间。...这种布局方式可以提供更大的用户空间地址范围,适用于需要大量内存的应用程序。 虚拟地址空间布局对于系统的性能和可用内存空间有一定的影响。选择合适的布局方式取决于系统的需求和应用程序的特性。...它用于随机化进程的虚拟地址空间布局,使攻击者难以预测内存布局并利用缓冲区溢出等漏洞。 该特性通过在 mmap() 系统调用期间随机化内存映射的基地址来工作。...可以通过内核中的配置选项来调整此范围。 随机化虚拟地址空间布局使攻击者更难成功发起攻击,因为他们需要猜测正确的内存地址进行攻击。
在磁盘地址表中有 13 个块号,文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。...malloc 用户空间下的内存管理接口,保证的是在虚拟地址空间上的连续。stack 和 heap 中间。小于128M的通过brk申请,大于的通过 mmap 申请。...Linux 内核空间布局x86架构中将内核地址空间划分三部分:ZONE_DMA、ZONE_NORMAL和 ZONE_HIGHMEM。ZONE_HIGHMEM即为高端内存,这就是内存高端内存概念的由来。...Linux 的内核空间和用户空间如何划分的?进程地址空间布局图?...在支持并使能 MMU 的系统中,Linux 内核和用于程序分别运行在物理地址模式还是虚拟地址模式?都运行在虚拟地址模式,页表转换对应由硬件单元MMU完成。12.
当然不是,$IO$ 的访问也是有特权级检查的,就算是内存映射直接读写内存的形式访问 $IO$,听着感觉很随意,但是这部分内存都是映射到虚拟地址的高地址处,也就是内核部分,只有内核(0 特权级)才有权操作...所以 $xv6$ 的空闲物理内存就可以看作是一个大链表。...当然不是的,其实我认为上述用户空间布局图关于堆稍稍有些问题,栈的上方到内核这一大片区域可以用作堆,但还不一定是堆。...准确点来说应该是下图这样: 图中有鲜明显色的区域都是实际映射到了物理内存的区域,其中蓝色部分才是 $malloc\ free$ 作用的区域,在 $Linux$ 中程序在内存中的映像有个属性叫做 $break...; uint eip; }; 同样是上下文,为什么内核态的就只用保存这么几个寄存器?
这篇文章是我在公司 TechDay 上分享的内容的文字实录版,本来不想写这么一篇冗长的文章,因为有不少的同学问是否能写一篇相关的文字版,本来没有的也就有了。...vitual_memory_mapping Linux 四级页表 但是这种方式有一个很明显的问题,虚拟地址空间可能会非常大,就算拿 32 位的系统为例,虚拟地址空间为 4GB,用户空间内存大小为 3GB...完整的代码见:https://github.com/arthur-zhang/virtualmem2physical 进程的内存布局 前面提到了虚拟内核和物理内存的关系,我们知道 linux 上的可执行文件的格式是...,这三个分别是 AMP,其中 A 表示是否是主分配区,M 表示是否是 mmap 分配的大 chunk 块,P 表示前一个 chunk 是否在使用中。...符合 fastbin 的超小块内存直接放入 fastbin 单链表,快速释放,画外音就是这么点空间,值得我处理半天吗? 超大块内存,直接还给内核不进入 bin 的管理逻辑。
spm=1001.2014.3001.5482 前言: 进程地址空间是操作系统进程管理的重要概念之一,它定义了进程在执行时所能访问的内存布局。...内核通过页表实现虚拟地址到物理地址的映射。 虚拟地址:由程序访问的地址。 物理地址:内存硬件实际使用的地址。 页表:存储虚拟地址到物理地址的映射关系。...这里我们重点讲解一下,此前在我们讲解父子进程时我们曾遗留了一个问题,那就是为什么 pid_t id = fork(); 中id能有两个值,为什么同一个地址空间下能有两个值呢?...4.2 /proc/[pid]/maps查看地址空间 在Linux系统中,可以通过/proc/[pid]/maps文件查看进程的地址空间布局。...内核空间 用于运行操作系统内核代码,存储内核数据结构,用户进程无法直接访问。 在32位系统中,通常用户空间占用地址的低3GB,内核空间占用地址的高1GB。
启动代码部分 本文来说码,实打实地来看看计算机到底是如何启动的,先来看看 $xv6$ 启动的整体流程图,好有个大概认识: 不要被这么一大坨吓到,$xv6$ 的启动过程算简单的,在启动方面做了很多简化,应该说整个操作系统都做了简化...再来看一眼内存低 $1M$ 的布局图: 所以没什么特殊意义,就是找了一块空闲地儿,来存放内核的开始的 4096 字节。 那这 4096 字节有什么用?这就加载内核了?...此时的内存布局: $end$ 为内核末尾地址,不同版本有稍许不同,可以在 $kernel.sym$ 文件中查找,也可以直接读取 $elf$ 的程序头,根据 $PhysAddr + MemSize$ 计算出来...②低地址,高地址问题,$bootmain.c$ 中的 $entry()$ 是怎么跳过来的 引导程序在物理内存的低 1M,内核程序在物理内存的 $1M, end$,后来临时页表将物理地址空间的 $[0,...为什么 $V2P$ 一个简单的宏就表示地址转化了见后面的内存管理部分,这里知道运用了这么一个宏就将虚拟地址转换为物理地址且赋给了 $_start$ 即可。
处理器以VA[20:12]作为L1索引,在L3页表中找到相应的页表项,L3页表中有512个页表项。...4-虚拟地址空间布局 当然虚拟地址空间划分不只是如此。因为目前应用程序没有那么大的内存需求,所以ARM64处理器不支持完全的64位虚拟地址,实际支持情况如下。...这个也就是大页表,可以提升内存与访问速度。 可以为虚拟地址配置比最大宽度小的宽度,并且可以为内核虚拟地址和用户虚拟地址配置不同的宽度。...在ARM64架构的Linux内核中,内核虚拟地址和用户虚拟地址的宽度相同。...小结 1-几个问题 (1)为什么没有MMU就无法运行Linux系统? 这是因为 Linux 内核将虚拟地址空间分为多个页面,并将这些页面映射到物理地址空间上,以实现内存隔离、保护和虚拟内存等功能。
领取专属 10元无门槛券
手把手带您无忧上云