我想知道mach_vm_allocate
和之间有什么区别vm_allocate
。我知道mach_vm_allocate
仅适用于 OS X 而不是 iOS,但我不知道为什么。mach_vm_...
包含函数的所有函数原型的文件(mach/mach_vm.h)
仅存#error mach_vm.h unsupported.
在于 iOS 中。
4 回答
Mac OS X 10.4 中引入的新 Mach VM API。从程序员的角度来看,新 API 与旧 API 基本相同,但有以下主要区别。
- 例程名称具有 mach_ 前缀例如, vm_allocate() 变为 mach_vm_allocate() 。
- 例程中使用的数据类型已更新为支持 64 位和 32 位任务。因此,新 API 可用于任何任务。
新旧 API 分别由不同的 MIG 子系统导出: mach_vm 和 vm_map 。对应的头文件分别是 <mach/mach_vm.h> 和 <mach/vm_map.h> 。
Mac OS X 10.4 中引入的新 Mach VM API。从程序员的角度来看,新 API 与旧 API 基本相同,但有以下主要区别:
例程名称有
mach_ prefixfor
例子,vm_allocate()
变为mach_vm_allocate()
;例程中使用的数据类型已更新为支持 64 位和 32 位任务。因此,新 API 可用于任何任务。
新旧 API 分别由不同的 MIG 子系统导出:mach_vm
和vm_map
。对应的头文件分别是<mach/mach_vm.h>
和<mach/vm_map.h>
。
该信息来自OS X Internals A System Approach一书。
这些将是 /usr/include/mach/mach_vm.h 和 /usr/include/mach/vm_map.h。您可以在 /usr/include/mach 中使用 grep 来获取这些内容。
在内核中,API 基本上使用相同的实现。在 iOS 上,您可以完美地使用“旧”API。
我对其他答案不满意。两个似乎引用了同一个来源(一个没有正确归因),这个来源相当具有误导性。
旧 API中的数据类型是可变大小的。如果你为 i386 CPU 架构编译,它们是 32 位的,如果你为 x86_64 CPU 架构编译,它们是 64 位的。
新 API中的数据类型是固定大小且始终为 64 位。
由于 32 位进程只需要 32 位数据类型,而 64 位进程即使使用旧 API 也已经具有 64 位类型,因此根本不知道为什么需要新 API。但是如果你看一下苹果的内核设计就会变得很明显:
macOS 的真正内核是Mach 3微内核。作为一个微内核,它只负责进程和线程管理、IPC、虚拟内存管理和进程/线程调度。就是这样。通常,使用 micros 内核时,其他所有操作都将在用户空间中完成,但这很慢,因此 Apple 采取了不同的方法。
Apple 采用 FreeBSD 单片内核并将其包裹在微内核周围,该微内核将 FreeBSD 内核作为具有特殊权限的单个进程(任务)执行(尽管是任务,但代码在内核空间而不是用户空间中运行,就像在系统)。组合内核的名称为XNU。
过去,Apple 支持在系统中混合 32 位和 64 位的任意组合:您的系统可以运行 32 位内核并在其上运行 32 位或 64 位进程,或者它可以运行 64 位内核并运行 32 位或 64 位对其进行处理。你可能已经看到了事情的发展方向,不是吗?
如果进程和内核的位宽不同,那么旧的 API 就没有用了。例如,32 位内核无法使用它与 64 位进程的内存进行交互,因为 API 调用的所有数据类型在 32 位内核任务中只能是 32 位,但 64 位进程甚至有 64 位内存空间如果内核本身没有。
实际上,该 API 甚至还有第三个版本。引用Apple 内核源代码的评论:
* There are three implementations of the "XXX_allocate" functionality in
* the kernel: mach_vm_allocate (for any task on the platform), vm_allocate
* (for a task with the same address space size, especially the current task),
* and vm32_vm_allocate (for the specific case of a 32-bit task). vm_allocate
* in the kernel should only be used on the kernel_task. vm32_vm_allocate only
* makes sense on platforms where a user task can either be 32 or 64, or the kernel
* task can be 32 or 64. mach_vm_allocate makes sense everywhere, and is preferred
* for new code.
只要您仅在用户空间中使用该 API 并且仅用于旧进程的内存管理,使用旧 API 仍然可以,即使对于 64 位进程,因为在这种情况下所有数据类型都是 64 位。
仅当跨进程边界工作并且不确定两个进程都是 32 位还是 64 位时才需要新的 API。但是,Apple 很久以前就放弃了 32 位内核支持,同时他们也放弃了 32 位用户空间支持,因为所有系统库从 10.15 (Catalina) 开始仅作为 64 位库提供。
在 iOS 上,从来不需要新的 API,因为你永远无法为 iOS 编写内核代码,而且 iOS 的安全概念禁止与其他进程空间直接交互。在 iOS 上,您只能使用该 API 与您自己的进程空间进行交互,因此它始终具有正确的数据类型。