linux - 根据分页分段存储器的程序生命周期

标签 linux memory-management operating-system x86

我对 x86 linux 机器中的分段和分页过程有一个令人困惑的概念。如果有人能阐明从头到尾涉及的所有步骤,我们将很高兴。

x86 使用分页分段内存技术进行内存管理。

谁能解释一下从可执行的 .elf 格式文件从硬盘加载到主内存到它消失的那一刻发生了什么。编译时,可执行文件中有不同的部分(文本、数据、堆栈、堆、bss)。这将如何加载?它们将如何在分页分段内存技术下设置。

想知道如何为加载的程序设置页表吗?想知道如何设置 GDT 表。寄存器是如何加载的?以及为什么说逻辑地址(由MMU的分段单元处理的是48位(段选择器的16位+ 32位偏移量)当它是32位机器时。其他16位将如何存储?从 ram 访问的任何东西都必须是 32 位或 4 字节如何访问其余的 16 位(以加载到段寄存器中)?

提前致谢。这个问题可以有很多东西。但想弄清楚可执行文件的整个生命周期。如果有人回答并就此展开讨论,我们将很高兴。

最佳答案

Unix 传统上通过分页实现保护。 286+提供分段,386+提供分页。每个人都使用分页,很少有人真正使用分段。

在 x86 中,每个内存操作数都有一个隐式段(因此地址实际上是 16 位选择器 + 32 位偏移量),具体取决于所使用的寄存器。因此,如果您访问 [ESP + 8],则隐含的段寄存器是 SS,如果您访问 [ESI],则隐含的段寄存器是 DS,如果您访问 [EDI+4],隐含的段寄存器是 ES,...您可以通过段前缀覆盖来覆盖它。

Linux 和几乎所有现代 x86 操作系统都使用平面内存模型(或类似的东西)。在平面内存模型下,每个段都提供对整个内存的访问,基数为 0,限制为 4Gb,因此您不必担心分段带来的复杂性。基本上有 4 个段:内核空间代码 (RX)、内核空间数据 (RW)、用户空间代码 (RX)、用户空间数据 (RW)。

ELF 文件由一些指向“程序段”和“节”的标题组成。部分用于链接。程序段用于加载。程序段通过 mmap() 映射到内存中,这会设置具有适当权限的页表条目。

现在,较旧的 x86 CPU 的分页机制仅提供 RW 访问控制(读取权限意味着执行权限),而分段提供 RWX 访问控制。结束权限兼顾了分段和分页(例如:RW(数据段)+R(只读页)=R(只读),而RX(代码段)+R(只读页)=RX(只读页)执行))。

所以有一些补丁通过分段提供执行预防:例如OpenWall 通过缩小代码段(具有执行权限的代码段)提供了一个不可执行的堆栈,并在页面错误处理程序中为任何需要从高内存地址执行的内容(例如:GCC trampolines,创建的自修改代码)提供了特殊的模拟在堆栈上有效地实现嵌套函数)。

关于linux - 根据分页分段存储器的程序生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8173887/

相关文章:

python - Amazon Polly ProfileNotFound : The config profile (adminuser) could not be found

javascript - 无法使用 cron linux 运行我的解析服务器的云代码功能

java - 从 jenkins 上传文件进行测试

c++ - 为什么我应该更喜欢使用免费商店而不是堆?

objective-c - UIView retainCount为0,但内存没有释放

android - 优化 GridLayout 的内存使用

linux - 如何在 C++ 中动态检查 posix 兼容系统中的库信息?

java - 在 Java 中使用 ssh2 连接到受 RSA SecurID 保护的 linux 系统

linux - 如何从 bash 中的字符串中获取数值

python - 如何从 python 脚本执行 cd 命令并在新终端中执行其他命令?