简体   繁体   English

如何让 Mac OS 在特定地址范围内分配内存?

[英]How can I ask Mac OS to allocate memory in a specific address range?

I am writing a Mac OS 9 "compatibility layer" for Mac OS X because I was struck with nostalgia recently, and because all current solutions require you to run Classic inside a virtual machine that doesn't support everything it should to run the stuff I want to use.我正在为 Mac OS X 编写 Mac OS 9“兼容层”,因为我最近对怀旧感到震惊,并且因为所有当前的解决方案都要求您在虚拟机中运行 Classic,而该虚拟机不支持运行我应该做的一切想用。

To achieve that goal, I implemented a PEF executable loader, a PowerPC interpreter that can bridge to native code, and some Mac OS 9 libraries.为了实现这个目标,我实现了一个 PEF 可执行加载器、一个可以桥接到本机代码的 PowerPC 解释器和一些 Mac OS 9 库。 The whole thing is kind of working: there are some bugs in the interpreter, but that was expected and I'm working on that.整个事情有点工作:解释器中有一些错误,但这是意料之中的,我正在努力。

My biggest issue so far is that PowerPC programs are 32-bits, so pointers need to be 32-bits.到目前为止,我最大的问题是 PowerPC 程序是 32 位的,因此指针必须是 32 位的。 To satisfy that constraint, currently I'm compiling for i386 only.为了满足该约束,目前我仅针对 i386 进行编译。 However, as I'm trying to build around that core, it's becoming more and more constraining (for instance, you can't use ARC with 32-bits Cocoa applications).但是,当我试图围绕该核心进行构建时,它变得越来越受限制(例如,您不能将 ARC 与 32 位 Cocoa 应用程序一起使用)。 Not to mention that it's not super-safe to let the PowerPC code access everything the host process can.更不用说让 PowerPC 代码访问宿主进程可以访问的所有内容并不是超级安全的。

I've designed the "platform" with an eventual switch to 64-bits in mind: the interpreter expects a base address and all PowerPC pointers are offset by that base address.我在设计“平台”时考虑到了最终切换到 64 位:解释器需要一个基地址,并且所有 PowerPC 指针都由该基地址偏移。 (Having a map that translates PowerPC addresses to native addresses is out of question, for performance and design reasons.) (出于性能和设计原因,拥有将 PowerPC 地址转换为本地地址的映射是不可能的。)

Since a 64-bits address space has enough room to host four billions independent 32-bits address spaces, this sounds like a good way to go for me.由于 64 位地址空间有足够的空间容纳 40 亿个独立的 32 位地址空间,这对我来说听起来是个好方法。

But I still have a problem: I need to be sure that I'll be able to allocate memory inside that address range, because it would be impossible for the PPC interpreter to access anything outside of it.但是我仍然有一个问题:我需要确保我能够在该地址范围内分配内存,因为 PPC 解释器不可能访问它之外的任何内容。

There are two solutions I am thinking of right now:我现在想到了两种解决方案:

  • Find out if I can ask Mac OS to allocate something inside a specific address range.看看我是否可以要求 Mac OS 在特定地址范围内分配一些东西。 I know I can use mmap , but mmap will ask for allocations in page multiples, which seems very wasteful to me since I'd need a full page for each allocation, no matter how small it is (though that could actually be okay considering that Classic-era Macs had very little memory compared to modern computers);我知道我可以使用mmap ,但是mmap会要求以页面倍数进行分配,这对我来说似乎很浪费,因为我需要为每个分配分配一个完整的页面,无论它有多小(尽管考虑到这实际上可能没问题)与现代计算机相比,经典时代的 Mac 内存很少);
  • Use mmap to reserve a full 0x100000000 bytes with PROT_NONE , then mprotect pages on demand to actually allocate memory when it's needed, and put them back to PROT_NONE when they're not useful anymore.使用mmapPROT_NONE保留完整的 0x100000000 字节,然后根据需要mprotect页面以在需要时实际分配内存,并在它们不再有用时将它们放回PROT_NONE It looks good on paper, but it means I have to implement a malloc replacement.它在纸面上看起来不错,但这意味着我必须实现malloc替换。

So, what should I do?所以我该怎么做? Is there a built-in mechanism that will let me try to allocate memory, malloc -style, inside a specific address range?是否有内置机制可以让我尝试在特定地址范围内分配malloc样式的内存? Otherwise, is there a good, readable, open-source implementation of malloc I could base myself on?否则,是否有我可以基于的良好的、可读的、开源的malloc实现?

I'm not aware of a built-in way to do this, but it is doable with a bit of work.我不知道有一种内置的方法可以做到这一点,但它可以通过一些工作来实现。 One approach would be to create a custom malloc zone, and then use malloc_zone_* versions of the usual malloc functions when allocating any memory that needs to be visible to your PPC code.一种方法是创建一个自定义 malloc 区域,然后在分配需要对您的 PPC 代码可见的任何内存时使用通常 malloc 函数的 malloc_zone_* 版本。 Your custom zone would need a malloc implementation, but you can pick from any number of open-source ones (eg tcmalloc).您的自定义区域将需要 malloc 实现,但您可以从任意数量的开源区域(例如 tcmalloc)中进行选择。 It would also need to be wired up to use something like vm_allocate with a hint address, to ensure you get allocations in the exact range you need.它还需要连接起来使用 vm_allocate 之类的东西和一个提示地址,以确保你在你需要的确切范围内获得分配。

So, I've considered this issue myself for a very similar (unpublished) project, and trying to use this 64-bit approach (or, indeed any sort of big-endian memory space on x86!) rapidly runs into a few nasty issues.所以,我自己在一个非常相似(未发布)的项目中考虑过这个问题,并尝试使用这种 64 位方法(或者,实际上是 x86 上的任何类型的大端内存空间!)迅速遇到一些令人讨厌的问题.

  1. While you can point native APIs at emulated structures, you can't force them to make all their own allocations within that arena.虽然您可以将本机 API 指向模拟结构,但您不能强迫它们在该领域内进行所有自己的分配。 You can provide your own implementations of all the most obvious ones, like _NewPointer , but internal allocations by other functions (like, say, _NewWindow with nil wStorage ) are largely out of your control.您可以提供所有最明显的实现,例如_NewPointer ,但其他函数的内部分配(例如, _NewWindow和 nil wStorage )在很大程度上不受您的控制。

  2. System structures (like a Rect, for instance) allocated by emulated code will be big-endian, but the OS will want them little-endian.由模拟代码分配的系统结构(例如 Rect)将是 big-endian,但操作系统会希望它们是 little-endian。 There's no easy way to get around this besides maybe byte-swapping everything on the way in and out of native functions, and that seems hugely error-prone.除了可能在进出本机函数的过程中对所有内容进行字节交换之外,没有简单的方法可以解决这个问题,而且这似乎非常容易出错。 (Another approach I considered here was to just make the emulated core run as little-endian, but some programs are, unfortunately, sensitive to this change.) (我在这里考虑的另一种方法是让模拟核心以小端模式运行,但不幸的是,有些程序对这种变化很敏感。)

To be clear, I love the hell out of the idea of a Classic-to-OS-X API translator.明确地说,我非常喜欢 Classic-to-OS-X API 转换器的想法。 But I'm pretty sure that it's impractical -- given that Apple ended using a VM for Classic on PPC, I suspect that they determined that a translation approach wasn't going to work.但我很确定这是不切实际的——鉴于 Apple 结束在 PPC 上使用 VM for Classic,我怀疑他们认为翻译方法行不通。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM