通过crash了解linux页表
目的:
通过一个c语言实例,了解linux页表的组织结果和mmu的工作原理。
通过页表找到一个物理地址, 对比物理地址与虚拟地址的内容是否一致。
运行环境:
$ uname -r
3.15.6-200.fc20.x86_64
准备工作
1. 安装crash
$ sudo yum install crash
熟悉crash
help:
http://people.redhat.com/anderson/help.html
White Paper:
http://people.redhat.com/anderson/crash_whitepaper/
1. 安装debuginfo
$ sudo debuginfo-install kernel
or
$ sudo yum install kernel-debuginfo
2. 下载一个linux源代码
可选
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
3. 准备一个C语言代码
熟悉linux页表使用。
hello.c
#include <stdio.h> void main()
{
char *str = "hello world";
printf("%s @ %p\n", str, str);
pause();
}
编译:
$ gcc -o hello hello.c
基本概念:
内核空间:
32位系统, linux将最上的1G用于内核虚拟地址。空间 0xc0000000 - 0xffffffff
linux将物理内存完全一一映射到内核空间,这样很方便管理内存,任何页面的(0M-896M的线性区)虚拟地址减去一个0xc0000000的偏移就可以得到物理地址。
有关64位的内核线性地址起始位置:
arch/x86/include/asm/page_64_types.h:#define __PAGE_OFFSET
_AC(0xffff880000000000, UL)
分页原理:
虚拟地址转化为物理地址过程。
MMU干的事情,就是 通过 PML + PUD + PMD + PTE 得出虚拟地址对应的真正的内存物理地址。
在64位系统, 虚拟地址才用4级分页(9+9+9+12)。 PML, PUD, PMD, PTE不是1024个项(因为每项是64位)是512。
不清楚PML是什么缩写,按照《内核》这本书的说法,应该是PGD (page directory)。
PUD(page upper directory) PMD(page middle directory)
PTE(page table entry)
假如我们的线性地址(虚拟地址)为0x400650(例子中的地址确实是400650),得到物理地址的过程如下:
每级页表(目录)索引值:
PML中的目录项: (0x400650>>(9+ 9 + 9 + 12)) & 0x1ff = 0
PUD中的目录项: (0x400650>>(9 + 9 + 12)) & 0x1ff = 0
PMD中的目录项: (0x400650>>(9 + 12)) & 0x1ff = 0x2
PTE中的目表项: (0x400650>>(12)) & 0x1ff = 0
在页中的偏移量(4K的页):
(0x400650>>(0)) & 0xfff = 0x650
图示转化过程:
cr3 包含页目录指针表, 假设为0x5427a000, 这是个物理地址。
每级页表包含下一级页表的信息。
下图,对于4K的页, PML的第0个目录项,0000000064e39067
为目录项中的内容,高(64-12)位(红色)是下一级页表的物理地址, 低位 12位是各种标志位(PRESENT|RW|USER|ACCESSED|DIRTY
)。

实践:
1. 运行 hello
$ ./hello
hello world @ 0x400650
2. 启动 crash
crash> ps |grep hello
24458 24204 0 ffff8801573b09e0 IN 0.0 4152 632 hello
crash> set 24458
PID: 24458
COMMAND: "hello"
TASK: ffff8801573b09e0 [THREAD_INFO: ffff880090794000]
CPU: 0
STATE: TASK_INTERRUPTIBLE
crash> px ((struct task_struct *)0xffff8801573b09e0)->mm->pgd
$1 = (pgd_t *) 0xffff88005427a000
crash> px (0xffff88005427a000 - 0xffff880000000000)
$2 = 0x5427a000 # 相当CR3中的内容, PML的首地址
crash> px $2 + 0x0 # PML的第0项
$3 = 0x5427a000
crash> rd -p 0x5427a000 #
5427a000: 0000000064e39067 g..d....
crash> pte 0000000064e39067
PTE PHYSICAL FLAGS
64e39067 64e39000 (PRESENT|RW|USER|ACCESSED|DIRTY) # 64e39000 PUD的首地址
crash> px (0x400650>>30) & 0x1ff
$4 = 0x0
crash> px 0x64e39000 + 0x0 # PUD 的第0项
$5 = 0x64e39000
crash> rd -p 0x64e39000
64e39000: 000000000b052067 g ......
crash> pte 000000000b052067
PTE PHYSICAL FLAGS
b052067 b052000 (PRESENT|RW|USER|ACCESSED|DIRTY) # b052000 PMD的首地址
crash> px (0x400650>>21) & 0x1ff
$6 = 0x2
crash> px 0xb052000 + 0x2 * 8 # PMD 的第2项
$7 = 0xb052010
crash> rd -p 0xb052010
b052010: 00000000ba5a6067 g`Z.....
crash> pte 00000000ba5a6067
PTE PHYSICAL FLAGS
ba5a6067 ba5a6000 (PRESENT|RW|USER|ACCESSED|DIRTY) # ba5a6000 PTE的首地址
crash> px (0x400650>>12) & 0x1ff
$8 = 0x0
crash> px 0xba5a6000 + 0x0 # PTE 的第0项
$9 = 0xba5a6000
crash> rd -p 0xba5a6000
ba5a6000: 000000001cdc5025 %P......
crash> pte 000000001cdc5025
PTE PHYSICAL FLAGS
1cdc5025 1cdc5000 (PRESENT|USER|ACCESSED) # 进程, 线性页对应的 真正的物理页框地址
crash> px 0x400650 & 0xfff
$10 = 0x650
crash> px 0x1cdc5000 + 0x650 # “hello world.%s” 所在 的物理地址。
$11 = 0x1cdc5650
crash> rd -p 0x1cdc5650 2
1cdc5650: 6f77206f6c6c6568 4020732500646c72 hello world.%s @
crash> vtop 0x400650 # 以上步骤可以一步搞定。
VIRTUAL PHYSICAL
400650 1cdc5650
PML: 5427a000 => 64e39067
PUD: 64e39000 => b052067
PMD: b052010 => ba5a6067
PTE: ba5a6000 => 1cdc5025
PAGE: 1cdc5000
PTE PHYSICAL FLAGS
1cdc5025 1cdc5000 (PRESENT|USER|ACCESSED)
VMA START END FLAGS FILE
ffff8800541f2228 400000 401000 8000875 /home/shhfeng/work/workdir/ccode/hello
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffea0000737140 1cdc5000 ffff88003fc40200 0 2 3ffff800020068 uptodate,lru,active,mappedtodisk
图示:
0x5427a000 0x0000000064e39000 0x000000000b052000 0x00000000ba5a6000 0x000000001cdc5000
+ 0 + 0
+0x2 * 8 (64位)
+ 0
+0x650
= 0x5427a000 =0x64e39000 = 0xb052010 = 0xba5a6000 = 0x1cdc5650
0 |0000000064e39067 | ----> 0 |000000000b052067
| ---> | |
----> 0 |000000001cdc5025 |-->
| |
| |
| | | |
| |
| | | |
| |
| | |---> 0x2 |00000000ba5a6067| |
| . |
|
| |
| |
| |
| | . |
|
| |
| |
| |
| | . -->0x650 |hello world.%s @ |
| |
| |
| |
| | | |
| |
| |
| |
| | | |
| |
| |
| |
| | | |
| |
| | |
| |
| |
|
PML
PUD
PMD
PTE 4K的page
通过crash了解linux页表的更多相关文章
- 【原创】ARMv8 MMU及Linux页表映射
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- linux页表机制
每个进程都拥有一个自己的页表,在linux中,有一个页目录数组,这是分页机制的最高层,每个进程的页表对应其中的一个页目录项,通过cr3寄存器可以访问. 一个进程的页表,对应的页表项中对应页的物理地址. ...
- Linux内存管理 (2)页表的映射过程
专题:Linux内存管理专题 关键词:swapper_pd_dir.ARM PGD/PTE.Linux PGD/PTE.pgd_offset_k. Linux下的页表映射分为两种,一是Linux自身的 ...
- Process Kill Technology && Process Protection Against In Linux
目录 . 引言 . Kill Process By Kill Command && SIGNAL . Kill Process By Resource Limits . Kill Pr ...
- linux处理闰秒
闰秒的介绍可以参考维基百科 https://zh.wikipedia.org/wiki/闰秒 linux处理闰秒 Linux使用UTC时钟,并通过NTP (Network time protocol) ...
- Android平台抓取native crash log
Android开发中,在Java层可以方便的捕获crashlog,但对于 Native 层的 crashlog 通常无法直接获取,只能通过系统的logcat来分析crash日志. 做过 Linux 和 ...
- Linux 虚存的性能问题
虚存子系统是所有 UNIX 系统的核心组件.下面讨论虚存系统的实现及其对操作系统中几乎其他所有子系统的作用和影响.首先详细说明一些基本的内存管理问题:然后具体分析 Linux 操作系统如何实施虚存管理 ...
- Linux内存管理 (1)物理内存初始化
专题:Linux内存管理专题 关键词:用户内核空间划分.Node/Zone/Page.memblock.PGD/PUD/PMD/PTE.lowmem/highmem.ZONE_DMA/ZONE_NOR ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
随机推荐
- struts2笔记09-动态方法调用
1.action配置 <action name="testDynamic" class="com.test.actions.TestAction"> ...
- jupyter巨好玩-简介与安装
ipython notebook改名jupyter了而且更好玩更好用 jupyter简介 jupyter是啥啊? 这个要从ipython说起,ipython是个交互式的python的解释器,自带颜色, ...
- 用实例给新手讲解RSA加密算法
图为 RSA公开密钥算法的发明人,从左到右Ron Rivest, Adi Shamir, Leonard Adleman. 照片摄于1978年 RSA加密算法是最常用的非对称加密算法,CFCA在证书服 ...
- elasticsearch 索引 类型 id
zjtest7-frontend:/usr/local/logstash-2.3.4/config# cat logstash_indexer01.conf input { redi ...
- ByteBuffer用法总结
转自:http://blog.csdn.net/mars5337/article/details/6576417 在NIO中,数据的读写操作始终是与缓冲区相关联的.读取时信道(SocketChanne ...
- Spring、Hello AOP
AOP 概念:http://blog.csdn.net/moreevan/article/details/11977115 AOP 所使用到的jar 包: aspectjrt.jar common-a ...
- Hibernate 、多表关联映射-组件关联映射(component)
组件关联映射可以将一些简小的数据与主题放在一个表中,例如firstName 和LastName这两个结合在一起可以组成一个名字,但是再分别将这两个再建一个表就不太合适了,这个时候可以用到组件关联映射: ...
- 404 Not Found The requested URL * was not found on this server
1. 把从SVNcheckout下来的代码搭建起来.CakePHP+mysql.改动数据库配置. 2. 配置虚拟主机,发现訪问不了/user/login这个URL,报这个错误:404 Not Foun ...
- VB.NET的反射机制
1.前提 Net的应用程序由几个部分:‘程序集’.‘模块’.‘类型’组成. 装配件是.Net应用程序执行的最小单位,编译出来的.dll..exe都是装配件. 2.概念 反射是获得运行时类型的方式. 概 ...
- 【找规律】CodeForce #258 Problem A——Game With Sticks
来源:点击打开链接 非常easy.找规律. 每去掉一个点,点的总数量就减去n+m-1,然后看谁最先减到没有点可减.就能够了. #include <iostream> #include &l ...