Linux页面表的过程

时间:2017-11-09 18:09:39

标签: linux assembly memory-management x86 virtual-memory

Intel core i5, Ubunu 16.04

我正在阅读有关内存分页here的信息,现在正试着尝试一下。 I wrote a simple assembly program for getting Segmentation Fault并在gdb中运行。这是:

 section .text
     global _start

 _start:
     mov rax, 0xFFFFFFFFFFFF0A31
     mov [val], eax
     mov eax, 4
     mov ebx, 1
     mov ecx, val
     mov edx, 2

     int 0x80

     mov eax, 1
     int 0x80

 segment .bss
     dummy resb 0xFFA
     val resb 1

我将它组装并链接到64位ELF静态可执行文件中。

据我所知,每个进程都有自己的页表,cr3注册指向该表。现在我想自己查看页面表?是否可以在Linux中找到有关进程页表的信息?

3 个答案:

答案 0 :(得分:3)

您需要将编译为内核模块的程序读取页表。我相信有一些项目可以做到这一点。

看看这里:https://github.com/jethrogb/ptdump

似乎描述了你想要的东西

答案 1 :(得分:1)

您可以在/proc/PID/smaps中查看您的流程所拥有的所有映射。这告诉您在没有获得SIGSEGV的情况下可以访问的内容。

cr3页面表格相同,因为内核并不总是“连接”所有映射。即硬件页面错误并不总是SIGSEGV:内核页面错误处理程序检查您的进程是否逻辑上已映射该内存并更正该情况,或者您是否确实违反了内存保护。

mmap()系统调用之后,或者在进程启动时映射文本/数据/ BSS段,你在逻辑上已经映射了内存,但是Linux可能已经决定是懒惰的并且还没有提供任何物理页面。 (例如,页面可能还没有在页面缓存中,因此在您尝试实际触摸该内存并出现页面错误之前无需阻止。)

或者对于BSS内存,多个逻辑页面可能会开始写入映射到零的同一物理页面的写入时复制。尽管根据Unix语义,您的内存是读写的,但页表实际上只具有只读映射。编写页面会出现页面错误,内核会将该条目指向一个零的新物理页面,然后在出现故障的指令返回到您的进程(然后将重新运行并成功)。

无论如何,这并不直接回答你的问题,但可能成为你真正想要的一部分。如果你想深入了解,那么确实可以看到实际的页面表,但通常不需要这样做。 smaps可以告诉你有多少映射驻留在内存中。

有关字段含义的详细信息,另请参阅what does pss mean in /proc/pid/smaps

顺便说一句,请参阅Why in 64bit the virtual address are 4 bits short (48bit long) compared with the physical address (52 bit long)?,了解4级页表格式的精彩图表(以及2M / 1G大页面如何适应)。

答案 2 :(得分:1)

  

我编写了一个简单的汇编程序来获取Segmentation Fault并在gdb中运行....据我所知,每个进程都有自己的Page表,其中cr3注册指向。现在我想自己查看页面表?是否可以在Linux中找到有关进程页表的信息?

操作系统维护页表。它们受到保护,不受用户模式访问(正如您尝试的那样)。

要了解保护的工作原理,您需要了解处理器模式(例如,内核和用户)之间的差异以及处理器在这些模式之间切换的方式。

但是,简而言之,尝试编写代码来检查页面表是不可能的。您最好从书本中学习页表结构,而不是尝试编写代码。我建议查看英特尔手册。

https://software.intel.com/en-us/articles/intel-sdm

可悲的是,这是相当干燥的,英特尔编写了我见过的最糟糕的处理器手册。我建议专门查看64位模式。英特尔的32位过于复杂。如果有关于段的讨论,那么您正在读取32位并且可以忽略它。英特尔的文档从未指定地址是物理的还是逻辑的。因此,您可能需要查看在线讲座以获得澄清。

要补充此读数,您可以查看Linux源代码。 https://github.com/torvalds/linux

总而言之,您似乎需要两个先决条件才能到达目的地:(1)处理器模式; (2)页表结构。