众所周知,内存管理是Linux内核中最基础,也是相当重要的部分。理解相关原理,不管是对内存的理解,还是对大家写用户态代码都很有帮助。很多书上、很多文章都写了相关内容,但个人总觉得内容太复杂,不是太容易理解,这里想用我自己理解的简单的方式来描述,希望能有所帮助。本篇文章由圆柱模板博主原创,转载需注明!

内存的分配

    大家写代码时,应该都会分配内存,不同语言,层次不同,使用的接口不同,不管使用哪种方式,在Linux系统中,基本上都会调用到C库的malloc接口,那就从malloc分配内存开始。

malloc就是用于分配一段内存,但这里分配到的内存并非物理内存,而是虚拟内存,这里没有严格区分虚拟地址、线性地址之类的概念,只会给大家添负担,也不深入讲述物理内存和虚拟内存的概念,书上通常有大量的篇幅介绍,大家可以简单这样理解:

  • 虚拟内存就是从进程的角度看,逻辑上的概念,并不实际存在;

  • 物理内存就对应物理上内存条上的内存;

  • 虚拟内存和物理内存有对应关系;
  • 虚拟内存分配时,相应的物理内存还没有分配;

虚拟内存到物理内存的映射

   由页表来建立虚拟内存到物理内存之间的映射关系。 页表就是在内存中的一张表,可以简单看做一张hash表,记录的是虚拟地址和物理地址的对应关系,每个虚拟地址对应一个表项,通过这张表,就能将虚拟地址转换为物理地址,也就能建立虚拟内存到物理内存的映射关系了。

  页表的使用

    页表有了,那谁来用呢?不可能是应用程序自己用吧,我写代码时好像从来都没见过页表?  当然,用户看到的只是虚拟地址(虚拟内存),其他的对用户都是透明的~  CPU中有个硬件单元,叫MMU(内存管理单元),页表就是给MMU硬件用的,MMU使用页表进行虚拟地址到物理地址的映射。也就是说,地址映射是由硬件完成的,软件(包括操作系统内核自身)都不管关心。  都说软件不用关心了,那我们为嘛还需要讲页表?  软件只是不用页表而且,但页表的创建和维护都是由软件(操作系统内核)负责的,也就是说我们(软件)创建虚拟内存和物理内存的映射关系,然后由硬件来自动进行地址映射(转换),我们不需要关心具体的转换过程。  前面说了,页表是在内存中,而页表是由软件创建的,那MMU如果知道页表到底在哪儿呢?  简单说,需要我们(软件)告诉它在哪儿,如何告诉?当然,写寄存器。CPU上有特别的寄存器(CR3),向其中写入页表的地址,MMU就知道了,然后硬件自己使用即可,我们就不管了。

页表的数量问题

   看似一张页表就能完成所有的地址映射了?  当然不行,如果是这样,虚拟内存就没有什么必要存在了。  这里又涉及新概念了:进程,这是操作系统中最基础的概念,其实不“新”。  系统中,所有任务都是以进程方式运行的,每个进程都有自己的独立的虚拟地址空间,好像又说复杂了,简单说,就是每个进程都有自己的虚拟内存,独立代表,其他进程看不到自己的虚拟内存,那么就意味着,每个进程都需要独立的虚拟内存到物理内存的映射,就是说,每个进程都需要自己的页表。  所以,系统中有多少进程,就有多少张页表。

  页表创建

简单来说,讨论linux页表就是讨论linux进程的的页表:linux页表的创建与更新都包含于进程的创建与更新中。当前的linux内核采用的是写时复制方法,在创建一个linux进程时,完全复制父进程的页表,并且将父子进程的页表均置为写保护(即写地址的时候会产生缺页异常等)。那么父子进程谁向地址空间写数据时,产生缺页异常,分配新的页,并将两个页均置为可写,按照这种方式父子进程的地址空间渐渐变得不同。     按照上面的分析, 只需要讨论第一个进程页表初始化,进程创建时页表的拷贝,以及缺页异常时页表的更新即可。

 什么是缺页异常

    简单说,就是硬件上的一种机制,当硬件检测到某种“不对”时,主动触发,然后会自动跳转到异常处理程序处理。异常跟中断类似,区别在于,中断是异步的,由外设触发;异常是同步的,由CPU自己触发。

好了,时间也比较晚了,就写到这,该睡觉了,明天又得早期了!明天晚上继续写写这些理论的东西!学习需要坚持!

我理解的Linux内存管理的更多相关文章

  1. 【转帖】linux内存管理原理深入理解段式页式

    linux内存管理原理深入理解段式页式 https://blog.csdn.net/h674174380/article/details/75453750 其实一直没弄明白 linux 到底是 段页式 ...

  2. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  3. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  4. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  5. Linux内存管理之slab分配器

    slab分配器是什么? 参考:http://blog.csdn.net/vanbreaker/article/details/7664296 slab分配器是Linux内存管理中非常重要和复杂的一部分 ...

  6. 自己写的书《深入理解Android虚拟机内存管理》,不出版只是写着玩

    百度网盘地址:https://pan.baidu.com/s/1jI4xZgE 我给起的书名叫做<深入理解Android虚拟机内存管理>.本书分为两个部分,前半部分主要是我对Linux0. ...

  7. Linux内存管理专题

    Linux的内存管理涉及到的内容非常庞杂,而且与内核的方方面面耦合在一起,想要理解透彻非常困难. 在开始学习之前进行了一些准备工作<如何展开Linux Memory Management学习?& ...

  8. 伙伴系统之避免碎片--Linux内存管理(十六)

    1 前景提要 1.1 碎片化问题 分页与分段 页是信息的物理单位, 分页是为了实现非连续分配, 以便解决内存碎片问题, 或者说分页是由于系统管理的需要. 段是信息的逻辑单位,它含有一组意义相对完整的信 ...

  9. 伙伴系统之伙伴系统概述--Linux内存管理(十五)

    在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, ...

随机推荐

  1. Idea开发环境中,开发springboot类型的项目,如果只引入parent节点,不添加依赖节点,maven是不会加载springboot的任何依赖的

    在SpringBoot类型的项目中,我本来是要使用pringBoot,创建一个Console项目,我原本在pom.xml中添加paren节点了,天真的认为不需要再添加其他任何依赖了,可是接下来的1个小 ...

  2. 解决IntelliJ IDEA 控制台输出中文乱码问题

    解决IntelliJ IDEA 控制台输出中文乱码问题 问题描述:如图,控制台输出的字符,乱码 解决方案 第一步:修改intellij idea配置文件: 找到Intellij idea安装目录,bi ...

  3. initramfs文件系统制作

    源码下载:https://busybox.net/downloads/ 源码版本:busybox-1.30.0.tar.bz2 [ 源码编译步骤 ] make menuconfig ARCH= COM ...

  4. 【Uiautomatorviewer】报错:Unexpected error while obtaining UI hierarchy java.lang.reflect.InvocationT...

    android 9.0系统不能用uiautomator识别 解决方法:android 8.0 以后 uiautomator 无法直接使用的问题https://www.cnblogs.com/copyw ...

  5. 2019-7-17 正则表达式和re模块

    一.re模块与正则表达式之间的关系 正则表达式不是python独有的,它是一门独立的技术 所有的编程语言都可以使用正则 但是如果你想在python中使用,你就必须依赖于re模块 正则的官方定义:正则表 ...

  6. The One day 中位数的计算

    """ 中位数是有序列表中间的数.如果列表长度是偶数,中位数则是中间两个数的平均值. 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / ...

  7. 使用canvas实现360水球波动

    代码如下: <!DOCTYPE html> <html lang="en">  <head>    <meta charset=" ...

  8. JAVA调用ORACLE存储过程时间类型参数没有日期

    是因为使用cs.setDate()给数据库传参数只会传日期部分.如果改用如下代码就可以: cs.setTimestamp(3, new java.sql.Timestamp(dKssj.getTime ...

  9. Java自学-类和对象 引用

    什么是Java中的引用? 引用的概念,如果一个变量的类型是 类类型,而非基本类型,那么该变量又叫做引用. 步骤 1 : 引用和指向 new Hero(); 代表创建了一个Hero对象 但是也仅仅是创建 ...

  10. Java自学-控制流程 结束外部循环

    Java中结束外部循环 Java中如何结束外部for循环? 示例 1 : 结束当前循环 break; 只能结束当前循环 public class HelloWorld { public static ...