江西建设厅网站证书查询,成都做小程序的开发公司,cms建站平台,建e室内设计网官网全景效果图linux内存管理#xff0c;内存管理好像离我们很远#xff0c;但这个知识点虽然冷门#xff08;估计很多人学完根本就没机会用上#xff09;但绝对是基础中的基础#xff0c;这就像武侠中的内功修炼#xff0c;学完之后看不到立竿见影的效果#xff0c;但对你日后的开发工…linux内存管理内存管理好像离我们很远但这个知识点虽然冷门估计很多人学完根本就没机会用上但绝对是基础中的基础这就像武侠中的内功修炼学完之后看不到立竿见影的效果但对你日后的开发工作是大有裨益的因为你站的更高了。
再功利点的说面试的时候不经意间透露你懂这方面知识并且能说出个一二三来也许能让面试官对你更有兴趣离升职加薪走上人生巅峰又近了一步。
虚拟地址
即使是现代操作系统中内存依然是计算机中很宝贵的资源看看你电脑几个T固态硬盘再看看内存大小就知道了。为了充分利用和管理系统内存资源Linux采用虚拟内存管理技术利用虚拟内存技术让每个进程都有4GB 互不干涉的虚拟地址空间。
进程初始化分配和操作的都是基于这个「虚拟地址」只有当进程需要实际访问内存资源的时候才会建立虚拟地址和物理地址的映射调入物理内存页。
打个不是很恰当的比方。这个原理其实和现在的某某网盘一样假如你的网盘空间是1TB真以为就一口气给了你这么大空间吗那还是太年轻都是在你往里面放东西的时候才给你分配空间你放多少就分多少实际空间给你但你和你朋友看起来就像大家都拥有1TB空间一样。
虚拟地址的好处
避免用户直接访问物理内存地址防止一些破坏性操作保护操作系统每个进程都被分配了4GB的虚拟内存用户程序可使用比实际物理内存更大的地址空间
4GB 的进程虚拟地址空间被分成两部分「用户空间」和「内核空间」 物理地址
上面章节我们已经知道不管是用户空间还是内核空间使用的地址都是虚拟地址当需进程要实际访问内存的时候会由内核的「请求分页机制」产生「缺页异常」调入物理内存页。
把虚拟地址转换成内存的物理地址这中间涉及利用MMU 内存管理单元Memory Management Unit ) 对虚拟地址分段和分页段页式地址转换关于分段和分页的具体流程这里不再赘述可以参考任何一本计算机组成原理教材描述。 Linux 内核会将物理内存分为3个管理区分别是
ZONE_DMA
DMA内存区域。包含0MB~16MB之间的内存页框可以由老式基于ISA的设备通过DMA使用直接映射到内核的地址空间。
ZONE_NORMAL
普通内存区域。包含16MB~896MB之间的内存页框常规页框直接映射到内核的地址空间。
ZONE_HIGHMEM
高端内存区域。包含896MB以上的内存页框不进行直接映射可以通过永久映射和临时映射进行这部分内存页框的访问。 相关视频推荐
linux内核内存管理操作系统底层原理全程干货内功修练的必备技能
【C开发】庞杂的内存问题如何理出自己的思路出来让你开发与面试双丰收
90分钟搞懂linux内存架构numa的优势slab的实现vmalloc的原理
免费学习地址c/c linux服务器开发/后台架构师
需要C/C Linux服务器架构师学习资料加qun812855908获取资料包括C/CLinuxgolang技术NginxZeroMQMySQLRedisfastdfsMongoDBZK流媒体CDNP2PK8SDockerTCP/IP协程DPDKffmpeg等免费分享 用户空间
用户进程能访问的是「用户空间」每个进程都有自己独立的用户空间虚拟地址范围从从 0x00000000 至 0xBFFFFFFF 总容量3G 。
用户进程通常只能访问用户空间的虚拟地址只有在执行内陷操作或系统调用时才能访问内核空间。
进程与内存
进程执行的程序占用的用户空间按照「 访问属性一致的地址空间存放在一起 」的原则划分成 5个不同的内存区域。 访问属性指的是“可读、可写、可执行等 。
代码段 代码段是用来存放可执行文件的操作指令可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改所以只准许读取操作它是不可写的。数据段 数据段用来存放可执行文件中已初始化全局变量换句话说就是存放程序静态分配的变量和全局变量。BSS段 BSS段包含了程序中未初始化的全局变量在内存中 bss 段全部置零。堆 heap 堆是用于存放进程运行中被动态分配的内存段它的大小并不固定可动态扩张或缩减。当进程调用malloc等函数分配内存时新分配的内存就被动态添加到堆上堆被扩张当利用free等函数释放内存时被释放的内存从堆中被剔除堆被缩减栈 stack 栈是用户存放程序临时创建的局部变量也就是函数中定义的变量但不包括 static 声明的变量static意味着在数据段中存放变量。除此以外在函数被调用时其参数也会被压入发起调用的进程栈中并且待到调用结束后函数的返回值也会被存放回栈中。由于栈的先进先出特点所以栈特别方便用来保存/恢复调用现场。从这个意义上讲我们可以把堆栈看成一个寄存、交换临时数据的内存区。
上述几种内存区域中数据段、BSS 段、堆通常是被连续存储在内存中在位置上是连续的而代码段和栈往往会被独立存放。堆和栈两个区域在 i386 体系结构中栈向下扩展、堆向上扩展相对而生。 你也可以再linux下用size命令查看编译后程序的各个内存区域大小
[lemon ~]# size /usr/local/sbin/sshdtext data bss dec hex filename
1924532 12412 426896 2363840 2411c0 /usr/local/sbin/sshd 内核空间
在 x86 32 位系统里Linux 内核地址空间是指虚拟地址从 0xC0000000 开始到 0xFFFFFFFF 为止的高端内存地址空间总计 1G 的容量 包括了内核镜像、物理页面表、驱动程序等运行在内核空间 。 直接映射区
直接映射区 Direct Memory Region从内核空间起始地址开始最大896M的内核空间地址区间为直接内存映射区。
直接映射区的896MB的「线性地址」直接与「物理地址」的前896MB进行映射也就是说线性地址和分配的物理地址都是连续的。内核地址空间的线性地址0xC0000001所对应的物理地址为0x00000001它们之间相差一个偏移量PAGE_OFFSET 0xC0000000
该区域的线性地址和物理地址存在线性转换关系「线性地址 PAGE_OFFSET 物理地址」也可以用 virt_to_phys()函数将内核虚拟空间中的线性地址转化为物理地址。
高端内存线性地址空间
内核空间线性地址从 896M 到 1G 的区间容量 128MB 的地址区间是高端内存线性地址空间为什么叫高端内存线性地址空间下面给你解释一下
前面已经说过内核空间的总大小 1GB从内核空间起始地址开始的 896MB 的线性地址可以直接映射到物理地址大小为 896MB 的地址区间。退一万步即使内核空间的1GB线性地址都映射到物理地址那也最多只能寻址 1GB 大小的物理内存地址范围。
请问你现在你家的内存条多大一般 PC 的内存都大于 1GB 了吧
所以内核空间拿出了最后的 128M 地址区间划分成下面三个高端内存映射区以达到对整个物理地址范围的寻址。而在 64 位的系统上就不存在这样的问题了因为可用的线性地址空间远大于可安装的内存。
动态内存映射区
vmalloc Region 该区域由内核函数vmalloc来分配特点是线性空间连续但是对应的物理地址空间不一定连续。 vmalloc 分配的线性地址所对应的物理页可能处于低端内存也可能处于高端内存。
永久内存映射区
Persistent Kernel Mapping Region 该区域可访问高端内存。访问方法是使用 alloc_page (_GFP_HIGHMEM) 分配高端内存页或者使用kmap函数将分配到的高端内存映射到该区域。
固定映射区
Fixing kernel Mapping Region 该区域和 4G 的顶端只有 4k 的隔离带其每个地址项都服务于特定的用途如 ACPI_BASE等。 回顾一下
上面讲的有点多先别着急进入下一节在这之前我们再来回顾一下上面所讲的内容。如果认真看完上面的章节我这里再画了一张图现在你的脑海中应该有这样一个内存管理的全局图。 内存数据结构
要让内核管理系统中的虚拟内存必然要从中抽象出内存管理数据结构内存管理操作如「分配、释放等」都基于这些数据结构操作这里列举两个管理虚拟内存区域的数据结构。
用户空间内存数据结构
在前面「进程与内存」章节我们提到Linux进程可以划分为 5 个不同的内存区域分别是代码段、数据段、BSS、堆、栈内核管理这些区域的方式是将这些内存区域抽象成vm_area_struct的内存管理对象。
vm_area_struct是描述进程地址空间的基本管理单元一个进程往往需要多个vm_area_struct来描述它的用户空间虚拟地址需要使用「链表」和「红黑树」来组织各个vm_area_struct。
链表用于需要遍历全部节点的时候用而红黑树适用于在地址空间中定位特定内存区域。内核为了内存区域上的各种不同操作都能获得高性能所以同时使用了这两种数据结构。
用户空间进程的地址管理模型 内核空间动态分配内存数据结构
在内核空间章节我们提到过「动态内存映射区」该区域由内核函数vmalloc来分配特点是线性空间连续但是对应的物理地址空间不一定连续。 vmalloc 分配的线性地址所对应的物理页可能处于低端内存也可能处于高端内存。
vmalloc 分配的地址则限于vmalloc_start与vmalloc_end之间。每一块vmalloc分配的内核虚拟内存都对应一个vm_struct结构体不同的内核空间虚拟地址之间有4k大小的防越界空闲区间隔区。与用户空间的虚拟地址特性一样这些虚拟地址与物理内存没有简单的映射关系必须通过内核页表才可转换为物理地址或物理页它们有可能尚未被映射当发生缺页时才真正分配物理页面。 总结一下
Linux内存管理是一个非常复杂的系统本文所述只是冰山一角从宏观角度给你展现内存管理的全貌这些知识在你和面试官聊天的时候还是够用的当然希望大家能够了解更深层次的原理。
这篇文章也可以作为一个索引一样的学习指南当你想深入某一点学习的时候可以在这些章节里找到切入点以及这个知识点在内存管理宏观上的位置。