OS X 10.8 - 系统调用后的地址空间布局



出于实验原因,我已经在我的OS X 10.8.2(运行x86 LP64内核)盒子上完全禁用了交换,我知道这是一个坏主意。

当我从任何应用程序进行系统调用时,地址空间布局是什么样的? 即现在,由于整个地址空间都已连接(没有交换),我可以确定性地从内核访问任何有效的用户地址并假设包含该地址的页面驻留在内存中吗?

我的理解是肯定的,但是在阅读后我有点困惑,无论用户空间是64位还是32位OS X内核始终以32位模式运行,并且整个过程地址空间被切换出来,整个4G被内核占用。这适用于 10.8.2 吗?如果是这种情况,那么我将无法从内核空间访问任何有效的用户空间地址,对吗?

即使在 64 位模式下,内核空间保留在地址空间的顶部(即 0xffffff8000xxxx),即使没有交换,也无法访问用户空间内存,除非您处于代表该用户空间进程的内核模式。原因是因为地址都是虚拟的,并且您依靠CR3(控制寄存器)来告诉MMU哪些物理页面属于哪个进程。因此,尽管原则上您可以在内核模式下访问所有内存,但如果没有 CR3,您将无法确定哪些页面属于哪个进程。

因此,在系统调用中,您可以将数据移入和移出用户模式内存(有 copyin/copyout,类似于 Linux 的 copy_[from/to]_user) - 这些也处理页面错误,以防页面实际交换,这是正常情况。但这仅适用于活动用户空间内存 - 即活动进程。当然,有一些黑客可以访问其他进程的CR3,但这些是非常不鼓励的(除非您正在编写高质量的恶意软件)。

首先,32 位内核/64 位用户空间安排是在 10.7(在客户端上)或 10.6(在服务器上)之前的情况。 10.5 及更早版本仅附带 32 位内核,10.6 和 10.7 附带 32 位和 64 位内核(默认取决于硬件),10.8 及更高版本仅具有 64 位内核。

其次,对于 64 位内核,OSX 确实使用拆分内核/用户虚拟地址布局。您是正确的,在用户空间和内核之间切换时,32 位几乎会交换整个 4GB。

至于直接取消引用用户空间指针 - 即使禁用交换也是一个坏主意,我永远不会发布这样的代码。如果你只是胡闹,你应该没事。(这真的很糟糕的一个原因是内存映射可以从另一个线程更改)

最新更新