1.概念

  • 内存管理模式

段式:内存分为了多段,每段都是连续的内存,不同的段对应不用的用途。每个段的大小都不是统一的,会导致内存碎片和内存交换效率低的问题。

页式:内存划分为多个内存页进行管理,如在 Linux 系统中,每一页的大小为 4KB。由于分了页后,就不会产生细小的内存碎片。但是仍然也存在内存碎片问题。

段页式:段式和页式结合。

  • 地址类型划分

逻辑地址:程序所使用的地址,通常是没被段式内存管理映射的地址,称为逻辑地址

线性地址:通过段式内存管理映射的地址,称为线性地址,也叫虚拟地址

虚拟地址:通过段式内存管理映射的地址,称为线性地址,也叫虚拟地址

物理地址:物理内存地址

说明:

  1. Inetel处理器中,逻辑地址是「段式内存管理」转换前的地址,线性地址则是「页式内存管理」转换前的地址。

  2. 段式内存管理映射而成的地址不再是“物理地址”了,Intel 就称之为“线性地址”(也称虚拟地址)。于是,段式内存管理先将逻辑地址映射成线性地址,然后再由页式内存管理将线性地址映射成物理地址。

  3. linux内存主要是页式内存管理,同时也有涉及段式机制。当前Linux内核所采取的办法是使段式映射的过程实际上不起什么作用。

  4. Intel最早处理器80286是纯段式管理,80386段式和页式均存在。

2.页式管理

  • x86架构32位cpu

    ​ 二级页表选址方式,一个内存页4KB大小,一级页目录表1024项,二级页表1024项,一个页表项4字节。一级页目录表项全部分配,二级页表在需要的时候创建。(局部性原理)。

    • 虚拟地址32位

      10+10+12,分别索引1级页表号,2级页表项,记录物理基地址的偏移地址。使用PAE机制之后32bit系统支持最大的内存是64GB(地址是32+4=36位)。

    • 线性地址寻址物理地址步骤

      1. 先根据10位寻址1级页表号,1级页表号中记录了2级页表的地址

      2. 找到2级页表地址后,接着根据虚拟地址的另10位寻找2级页表中表项的位置

      3. 找到2级页表的表项之后,表项中记录了该虚拟地址映射物理地址的起始地址,表项的大小是4字节32bit

      4. 根据找到的物理地址的起始地址结合虚拟地址的后12位作为偏移计算出最终的物理地址

  • x86架构 64位cpu

    • 存在更多级页表

      1. 全局页目录项 PGD(Page Global Directory
      2. 上层页目录项 PUD(Page Upper Directory)
      3. 中间页目录项 PMD(Page Middle Directory)
      4. 页表项 PTE(Page Table Entry)
    • 线性地址寻址物理地址步骤

      1. 线性地址为48bit,最大物理地址为52bit,实际物理内存地址总线宽度是40bit,也就是支持1TB物理内存
      2. x86_64有四级页表,原理同x86系统,也是一层层的寻址
      3. CR3寄存器保存最高层一级表的起始物理地址,因此寻址首先就是要获取到CR3寄存器中的值
      4. 每个PTE表项的大小是8个字节也就是64bit

  • TLB

    在 CPU 芯片中,加入了一个专门存放程序最常访问的页表项的 Cache,这个 Cache 就是 TL(Translation Lookaside Buffer) 。通常称为页表缓存、转址旁路缓存、快表等。那么在CPU的内存管理单元MMU寻址时,会先查 TLB,如果没找到,才会继续查常规的页表。

  • 专有名词

    PDT:页目录表,多级页表一级页表,32bit系统有1024个页目录

    PTT:页表项表,多级页表二级页表,32bit系统有每个页目录下有1024个页表项,每个表项4个字节

    PDE:页表的基址,是PDT中一项

    PTE:是页的基址,是PTT中一项

    GDT:全局描述符表,逻辑地址转为线性地址用到

    LDT:局部描述符表,逻辑地址转为线性地址用到

3.地址划分

  • 32系统

    内核1G: 0xC0 00 00 01 - 0xFF FF FF FF

    用户3G: 0x00 00 00 00 - 0xC0 00 00 00

    0xC0 00 00 00 == 3G

  • 64位系统:

    内核128T: 0xFF FF 80 00 00 00 00 00 - 0xFF FF FF FF FF FF FF FF (高位)

    0xFF FF 7F FF FF FF FF FF - 0xFF FF FF FF FF FF FF FF(自己计算)

    用户128T: 0x00 00 00 00 00 00 00 00 - 0x00 00 7F FF FF FF FF FF (低位)

    0x00 00 80 00 00 00 00 00 - 0x00 00 80 00 00 00 00 00 (自己计算)

​ 0x00 00 7F FF FF FF FF FF == 127T

​ 疑问:64位系统128T是分界线是127T?

  • 访问权限

    进程在用户态时,只能访问用户空间内存

    只有进入内核态后,才可以访问内核空间的内存

  • PAE机制

    ​ CPU位宽指的是一个时钟周期内CPU能处理的二进制位数,普通场景中32位系统CPU的地址总线可以是32位,但是引入了PAE机制之后,16位CPU的地址总线位宽可以是20位(物理内存1M),32位CPU的地址总线可以是36位(物理内存64GB),64位CPU的地址总线位宽可以是40位(物理内存1TB)。因此我们不能简单的说32位系统只支持最大4GB的内存条。

4. 调试

  • 程序寄存器

    cs:是代码段寄存器

    ds:是数据段寄存器

    ss:是堆栈段寄存器

    es:是扩展段寄存器

    fs:是标志段寄存器 32位之后才有

    gs:是全局段寄存器 32位之后才有

    示例一个内核宕机的日志:

    RIP: 0010:[] [] xxxxxxxxxx+0x69/0x70

    RSP: 0018:ffff886241737d98 EFLAGS: 00010246

    RAX: ffff880034814d40 RBX: ffff881fc6248740 RCX: 0000000000000200

    RDX: 0000000000000000 RSI: 0000000000000286 RDI: ffff881fc6381858

    RBP: ffff886241737d98 R08: ffff886241734000 R09: 0000000000000000

    R10: ffff880034814d40 R11: 0000000000000200 R12: ffff881fc62487a0

    R13: 0000000000000000 R14: 00007fff86cb6260 R15: ffff881fc6381858

    FS: 00007f78b59b8720(0000) GS:ffff885ffe3c0000(0000) knlGS:0000000000000000

    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033

    CR2: 00007f690a057180 CR3: 0000006208985000 CR4: 00000000003627e0

    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000

    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

  • 查看程序寄存器

    使用GDB随意调试一个linux 32位上的ELF32的可执行文件,使用info r命令查看一下寄存器情况:

    段寄存器有0x23和0x2b两种情况:

    十六进制:0023

    二进制:0000000000100 0 11 - 段序号:4 - 表类型:GDT - 特权级:Ring3

    十六进制:002B

    二进制:0000000000101 0 11 - 段序号:5 - 表类型:GDT - 特权级:Ring3

    段序号:从第四位开始 表类型:第三位 特权级:第1、2位

    Linux下没有找到可以直接用什么命令或者工具查看GDT的方式,于是去源代码中寻找答案:

    看到了吗,这两项所描述的段和Windows一样,基地址为0,大小为4GB。

    Windows和Linux都选择了通过这种方式架空了CPU的分段内存管理机制。

    但需要说明一下的时,虽然两个操作系统都是这种情况,但并不意味着段机制彻底没用到,CPU的任务管理TSS还是需要用到,这一点大家知道就行了,在linux64位系统下分段机制不被待见,但是操作系统仍然会保持先分段再分页的寻址方式。

    5.参考资料:

    图形化解释内存:https://segmentfault.com/a/1190000023055534#item-2-6

    图形代码结合:https://www.cnblogs.com/alantu2018/p/9177356.html

    当代操作系统内存管理:https://www.cnblogs.com/xuanyuan/p/15266447.html

    GDT:https://en.wikipedia.org/wiki/Global_Descriptor_Table

    线性地址转为物理地址实践:https://www.cnblogs.com/onetrainee/p/11721946.html

    64位系统40位物理地址解释:https://zhuanlan.zhihu.com/p/69334474

Linux内存管理和寻址详解的更多相关文章

  1. Linux内存管理之mmap详解

    转发之:http://blog.chinaunix.net/uid-26669729-id-3077015.html Linux内存管理之mmap详解 一. mmap系统调用 1. mmap系统调用  ...

  2. Linux 内存管理之mmap详解

    找了好多,最后发现下面这篇时讲的比较通俗易懂的. Linux内存管理之mmap详解-heavent2010-ChinaUnix博客 http://blog.chinaunix.net/uid-2666 ...

  3. 转:Linux内存管理之mmap详解

    一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进内存.文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零.munmap执行相 ...

  4. [转载] Linux内存管理之mmap详解

    转载自http://blog.chinaunix.net/uid-26669729-id-3077015.html 一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进 ...

  5. Linux内存管理之mmap详解 【转】

    转自:http://blog.chinaunix.net/uid-26669729-id-3077015.html 一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进 ...

  6. Linux内存管理之mmap详解 (可用于android底层内存调试)

    注:将android底层malloc换为mmap来获取内存,可将获取到的内存添加tag,从而再利用meminfo进行分析,可单独查看该tag的内存,从而进行分析. 一. mmap系统调用 1. mma ...

  7. Linux服务管理 systemctl命令详解

    Linux服务器,服务管理--systemctl命令详解,设置开机自启动 syetemclt就是service和chkconfig这两个命令的整合     任务 旧指令 新指令 使某服务自动启动 ch ...

  8. Linux权限管理命令chmod详解

    命令chmod详解 命令chmod(英文原意:change permissions mode of a file),所在路径为: 可以看到,它的路径为:/usr/bin/chmod,因此,它的执行权限 ...

  9. JVM内存管理--GC算法详解

    标记/清除算法 首先,我们回想一下上一章提到的根搜索算法,它可以解决我们应该回收哪些对象的问题,但是它显然还不能承担垃圾搜集的重任,因为我们在程序(程序也就是指我们运行在JVM上的JAVA程序)运行期 ...

随机推荐

  1. 牛客网 剑指Offer 索引

    二维数组中的查找 替换空格 从尾到头打印链表 重建二叉树 用两个栈实现队列 旋转数组的最小数字 斐波那契数列 跳台阶 变态跳台阶 矩形覆盖 二进制中1的个数 数值的整数次方 调整数组顺序使奇数位于偶数 ...

  2. F. Mattress Run 题解

    F. Mattress Run 挺好的一道题,对于DP的本质的理解有很大的帮助. 首先要想到的就是将这个拆成两个题,一个dp光求获得足够的夜晚的最小代价,一个dp光求获得足够的停留的最小代价. 显然由 ...

  3. hdu 2571 命运(水DP)

    题意: M*N的grid,每个格上有一个整数. 小明从左上角(1,1)打算走到右下角(M,N). 每次可以向下走一格,或向右走一格,或向右走到当前所在列的倍数的列的位置上.即:若当前位置是(i,j), ...

  4. hdu 2147 kiki's game(DP(SG)打表找规律)

    题意: n*m的棋盘,一枚硬币右上角,每人每次可将硬币移向三个方向之一(一格单位):左边,下边,左下边. 无法移动硬币的人负. 给出n和m,问,先手胜还是后手胜. 数据范围: n, m (0<n ...

  5. 学会python永不加班系列之操作excel

    python作为一种解释性语言,简单高效的模式逐渐火爆.同时存在多种扩展性. 永不加班系列 python正确操作excel 实验环境: 系统:win10 语言:python3.8 承载软件:pycha ...

  6. docker commit 制作自定义tomcat镜像

    官网下载的tomcat一般存在漏洞,在生产环境中一般是自己下载jdk和tomcat制作成一个新的镜像使用 1.将jdk和tomcat上传 2.生成 c3 容器 3.将jdk和tomcat拷贝到c3容器 ...

  7. 力扣 - 剑指 Offer 66. 构建乘积数组

    题目 剑指 Offer 66. 构建乘积数组 思路1 按照一般的思路就是将所有的相乘,然后除以每一位数字就是答案,但是题目要求我们不能使用除法,因此我们会想到每次遍历到每个数字的时候,在遍历一遍数组, ...

  8. robot framework 常用关键字介绍

    1.log 打印所有内容 log hello word 2.定义变量 ${a} Set variable 92 log ${a}   3.连接对象 ${a} Catenate hello word l ...

  9. [后端及服务器][WSL2(Ubuntu)+Docker]从零开始在WSL中安装Docker

    目录 简介 WSL 安装 开启虚拟化(BIOS) 检查系统版本 安装WSL 老版本安装详情 简介 想花三篇文章写下从Windows(WSL)上开启Docker部署php/node/vue/html等项 ...

  10. Python多版本共存的方法

    目录 Python2.Python3共存的方法 python2下载及环境变量配置 第一步.打开Python官网,下载Python2 第二步.python2环境变量配置 测试结果 Python2.Pyt ...