首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不使用分段机制的情况下,如何在x86中管理堆栈和堆段?

在不使用分段机制的情况下,如何在x86中管理堆栈和堆段?
EN

Stack Overflow用户
提问于 2022-02-13 16:38:56
回答 1查看 244关注 0票数 0

从理解Linux内核开始

80x86微处理器中包含了分段,以鼓励程序员将应用程序拆分为逻辑相关的实体,例如子程序或全局和本地数据区域。然而,以非常有限的方式使用分段。实际上,分段和分页有些多余,因为两者都可以用于分离进程的物理地址空间:分段可以为每个进程分配不同的线性地址空间,而分页可以将相同的线性地址空间映射到不同的物理地址空间。Linux更喜欢分页而不是分段,原因如下:

  • 当所有进程都使用相同的段寄存器值时,即当它们共享同一组线性地址时,内存管理就更简单了。
  • Linux的设计目标之一是可移植到广泛的体系结构;尤其是RISC体系结构对分段的支持有限。

2.6版本的Linux只在80x86体系结构需要时才使用分段。

x86-64体系结构在长模式(64位模式)中不使用分段.由于x86有段,所以不可能不使用它们。四个段寄存器: CS、SS、DS和ES强制为0,限制为2^64。如果是这样,则提出两个问题:

  • 堆栈数据(堆栈段)和堆数据(数据段)混合在一起,然后从堆栈中弹出并增加ESP寄存器是不可用的。
  • 操作系统如何知道特定虚拟内存地址中的数据类型(堆栈还是堆)?
  • 不同的程序如何通过共享内存共享内核代码?
EN

回答 1

Stack Overflow用户

发布于 2022-02-13 19:54:14

堆栈数据(堆栈段)和堆数据(数据段)混合在一起,然后从堆栈中弹出并增加ESP寄存器是不可用的。

正如Peter在上述评论中所述,尽管CS、SS、ES和DS都被视为零基,但这并不会以任何方式改变PUSH/POP的行为。它与任何其他段描述符的使用并没有什么不同。即使在32位多段模式下,如果将多个选择器指向相同的描述符,也可以得到重叠段。在64位模式下唯一的“更改”是,您有一个由CPU强制使用的基,RSP可以用来指向可寻址内存中的任何位置。推送/弹出操作将像往常一样工作。

操作系统如何知道特定虚拟内存地址中的数据类型(堆栈还是堆)?

用户空间程序可以(也会)随意移动堆栈和堆.操作系统并不真正需要知道堆栈和堆在哪里,但它可以在一定程度上跟踪这些堆栈,假设用户空间应用程序按照约定执行所有操作,即使用内核在程序启动时分配的堆栈,将程序中断作为堆使用。

使用内核在程序启动时分配的堆栈,或者使用mmap(2)MAP_GROWSDOWN获得的内存区域,内核试图在内存区域超出其大小(即堆栈溢出)时自动增长内存区域,但这是有其局限性的。手动MAP_GROWSDOWN映射在实践中很少使用(参见123.4.)。POSIX线程和其他更现代的实现对线程使用固定大小的映射。

“堆”是现代用户空间应用中一个相当抽象的概念。Linux为用户空间应用程序提供了操纵程序的基本能力,突破了brk(2)sbrk(2),但这很少与我们现在所习惯的“堆”相对应。因此,一般来说,内核不知道应用程序的堆驻留在哪里。

不同的程序如何通过共享内存共享内核代码?

这只是通过分页来完成的。您可以说内核有一个页面表的层次结构,对于用户空间进程有许多其他的层次结构(每个任务都有一个)。当切换到内核空间(例如通过syscall)时,内核会更改CR3寄存器的值,使其指向内核的页面全局目录。当切换回用户空间时,CR3会更改为指向当前进程的页面全局目录,然后再赋予用户空间代码控制权。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71102775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档