Linux内存管理图解【转】

简介: 转自:http://www.360doc.com/content/13/0505/15/12218157_283128759.shtml Linux内存管理图解 2013-05-05  果儿的百科  文章来源   Linux内存管理图解作者:wdy二、线性地址转物理地址前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。

转自:http://www.360doc.com/content/13/0505/15/12218157_283128759.shtml

Linux内存管理图解

2013-05-05   果儿的百科  文章来源
 
Linux内存管理图解
作者:wdy

二、线性地址转物理地址

前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。

分页是CPU提供的一种机制,Linux只是根据这种机制的规则,利用它实现了内存管理。

分页的基本原理是把线性地址分成固定长度的单元,称为页(page)。页内部连续的线性地址映射到连续的物理地址中。X86每页为4KB(为简化分析,我们不考虑扩展分页的情况)。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table),页表存放在内存中。

在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。如果PG=0,则分页机制无效,线性地址就直接作为物理地址。

为了实现每个任务的平坦的虚拟内存和相互隔离,每个任务都有自己的页目录表和页表。

为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。

32位的线性地址被分成3个部分:

最高10位 Directory 页目录表偏移量,中间10位 Table是页表偏移量,最低12位Offset是物理页内的字节偏移量。

页目录表的大小为4KB(刚好是一个页的大小),包含1024项,每个项4字节(32位),表项里存储的内容就是页表的物理地址(因为物理页地址4k字节对齐,物理地址低12位总是0,所以表项里的最低12字节记录了一些其他信息,这里做简化分析)。如果页目录表中的页表尚未分配,则物理地址填0。

页表的大小也是4k,同样包含1024项,每个项4字节,内容为最终物理页的物理内存起始地址。

<ignore_js_op>Linux02.gif 

每个活动的任务,必须要先分配给它一个页目录表,并把页目录表的物理地址存入cr3寄存器。页表可以提前分配好,也可以在用到的时候再分配。

还是以 mov    0x80495b0, %eax  中的地址为例分析一下线性地址转物理地址的过程。

前面说到Linux中逻辑地址等于线性地址,那么我们要转换的线性地址就是0x80495b0。转换的过程是由CPU自动完成的,Linux所要做的就是准备好转换所需的页目录表和页表(假设已经准备好,给页目录表和页表分配物理内存的过程很复杂,后文再分析)。

内核先将当前任务的页目录表的物理地址填入cr3寄存器。

线性地址 0x80495b0 转换成二进制后是 0000 1000 0000 0100 1001 0101 1011 0000,最高10位0000 1000 00的十进制是32,CPU查看页目录表第32项,里面存放的是页表的物理地址。线性地址中间10位00 0100 1001 的十进制是73,页表的第73项存储的是最终物理页的物理起始地址。物理页基地址加上线性地址中最低12位的偏移量,CPU就找到了线性地址最终对应的物理内存单元。

我们知道Linux中用户进程线性地址能寻址的范围是0 - 3G,那么是不是需要提前先把这3G虚拟内存的页表都建立好呢?一般情况下,物理内存是远远小于3G的,加上同时有很多进程都在运行,根本无法给每个进程提前建立3G的线性地址页表。Linux利用CPU的一个机制解决了这个问题。进程创建后我们可以给页目录表的表项值都填0,CPU在查找页表时,如果表项的内容为0,则会引发一个缺页异常,进程暂停执行,Linux内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。

怎样防止进程访问不属于自己的线性地址(如内核空间)或无效的地址呢?内核里记录着每个进程能访问的线性地址范围(进程的vm_area_struct 线性区链表和红黑树里存放着),在引发缺页异常的时候,如果内核检查到引发缺页的线性地址不在进程的线性地址范围内,就发出SIGSEGV信号,进程结束,我们将看到程序员最讨厌看到的Segmentation fault。
【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
1月前
|
存储 Linux 编译器
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
50 0
|
Linux
【Linux】—— 共享内存
【Linux】—— 共享内存
|
2月前
|
Linux
linux 内存碎片查看
linux 内存碎片查看
44 3
|
30天前
|
存储 算法 Linux
【Linux 应用开发 共享内存】深入理解和实践 ftruncate:共享内存的有效管理
【Linux 应用开发 共享内存】深入理解和实践 ftruncate:共享内存的有效管理
62 5
|
1月前
|
Shell Linux C语言
【Shell 命令集合 磁盘维护 】Linux 创建一个初始化内存盘 mkinitrd命令使用教程
【Shell 命令集合 磁盘维护 】Linux 创建一个初始化内存盘 mkinitrd命令使用教程
35 0
|
5天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
17天前
|
存储 缓存 监控
Linux内存和硬盘空间管理技巧
了解Linux内存和硬盘管理技巧,提升系统性能和稳定性。使用`free`, `top`, `vmstat`监控内存,通过`sync`, `echo 1 &gt; /proc/sys/vm/drop_caches`清理缓存。利用Swap分区释放内存。借助`df`, `du`检查硬盘空间,清理无用文件,使用`clean-old`, `gzip`, `tar`压缩归档。查找大文件用`find`和`du`,确保
33 0
|
18天前
|
Prometheus 监控 Cloud Native
【Linux】查看系统内存命令(详细讲解)
【Linux】查看系统内存命令(详细讲解)
|
22天前
|
存储 缓存 监控
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
|
30天前
|
存储 缓存 监控
Linux 系统 内存通用指标以及查询方式
Linux 系统 内存通用指标以及查询方式
18 0