【问题标题】:Linux page table of the processLinux进程的页表
【发布时间】:2018-04-22 20:34:27
【问题描述】:
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 中找到有关进程页表的信息?

【问题讨论】:

  • 应用程序不能访问页表,只有内核可以访问。
  • @Barmar 但也许我们可以在/proc 或Linux 的其他地方找到一些信息?
  • Unix.stackexchange.com 可能是一个更好的地方来询问这个问题。
  • @Barmar Btw,我们可以在 gdb 中找到一些关于它的信息吗?
  • 还要注意它一直在变化。除非您将页面锁定在内存中,否则这将是非常无用的信息。

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


【解决方案1】:

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

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

似乎描述了你想要什么

【讨论】:

  • 如果您不能提供更具体的细节,这似乎更适合作为评论。
【解决方案2】:

您可以在/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 巨页如何适应)。

【讨论】:

    【解决方案3】:

    我编写了一个简单的汇编程序来获取分段错误并在 gdb 中运行....据我所知,每个进程都有自己的页表,cr3 寄存器指向该页表。现在我想自己查看页表?是否可以在 Linux 中找到有关进程页表的信息?

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

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

    然而,简而言之,尝试编写代码来检查页表是一条死胡同。您最好从书籍中学习页表结构,而不是尝试编写代码。我建议查看英特尔手册。

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

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

    为了补充这篇文章,您可以查看 Linux 源代码。 https://github.com/torvalds/linux

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

    【讨论】:

    • 没有什么能阻止您编写一个 Linux 内核模块,该模块为调用进程拍摄页表快照,并通过 IOCTL(或其他一些机制)之类的方式将其提供给用户进程跨度>
    • 但是很明显,这家伙没有达到这个水平,也没有使用内核模式调试器。
    猜你喜欢
    • 1970-01-01
    • 2020-08-19
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 2017-02-02
    • 2023-03-17
    相关资源
    最近更新 更多