我使用的是ARM64系統(tǒng)(M1)。
$ uname -m
arm64
這是我用來(lái)查找系統(tǒng)上虛擬地址空間范圍的C程序。
#include <stdlib.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
int main(void) {
printf("Page size = %d\n", getpagesize());
struct rlimit x;
getrlimit(RLIMIT_AS, &x);
printf("Current maximum size = %llx\n", x.rlim_cur);
printf("Limit on maximum size = %llx\n", x.rlim_max);
unsigned long long int value = 0;
value -= 1;
printf("Maximum float = %llx", value);
return 0;
}
Output:
Current maximum size = 7fffffffffffffff // 9223372036854775807
Limit on maximum size = 7fffffffffffffff // 9223372036854775807
Maximum float = ffffffffffffffff // 18446744073709551615
最大大小似乎是2^63-1。最后一位根本沒(méi)有被使用。
為什么會(huì)出現(xiàn)這種情況?在64位系統(tǒng)上,虛擬內(nèi)存地址范圍應(yīng)為2^64- 1正確的
我知道地址只使用48位,但這似乎與地址空間的范圍無(wú)關(guān)(為什么32位和64位的地址有兩種不同的長(zhǎng)度?)
就arm64硬件而言,EL0和EL1共享一個(gè)轉(zhuǎn)換機(jī)制,
TTBR0_EL1
和TTBR1_EL1
分別控制地址空間的下半部分和上半部分。通常下半部分用于userland,上半部分用于內(nèi)核。但首先要注意的是,
rlimit
與硬件無(wú)關(guān)。這是關(guān)于操作系統(tǒng)的。XNU有這個(gè)(它也被復(fù)制到蘋果的SDK中):
所以這只是“無(wú)限制”的值。
作為第二個(gè)注意事項(xiàng),盡管有
RLIMIT_AS
的描述,但這與地址空間大小無(wú)關(guān)。這大約是流程中所有現(xiàn)有映射的總和。arm64 XNU允許映射內(nèi)存的實(shí)際最大地址是0x00007ffffe000000。這個(gè)值只是對(duì)macOS進(jìn)行了硬編碼。還有一個(gè)最小地址,在進(jìn)程初始化時(shí)設(shè)置為進(jìn)程中主二進(jìn)制的基地址(通常為0x100000000)加上ASLR幻燈片。
在macOS以外的蘋果操作系統(tǒng)上,最大地址的規(guī)則更為復(fù)雜,但以下是相關(guān)的代碼位:
osfmk/mach/arm/vm_param.h
:osfmk/mach/shared_region.h
:osfmk/arm/pmap/pmap.c
:因此,在iOS和其他non-macOS配置上,如果您有“jumbo”映射(您可以使用
com.apple.developer.kernel.extended-virtual-addressing
權(quán)限獲得,或者在一些具有com.apple.developer.kernel.increased-memory-limit
的設(shè)備上獲得),則地址大小限制為0x0000000fc0000000,否則為0x00000002a0000000、0x00000002b8000000或0x00000003b8000000,具體取決于設(shè)備的物理內(nèi)存量。請(qǐng)注意,后三個(gè)大小可能會(huì)發(fā)生變化,因?yàn)樗鼈兪歉鶕?jù)共享緩存區(qū)域邊界的大小計(jì)算的,而共享緩存區(qū)域本身也會(huì)發(fā)生變化。"9.375GB"和"13.375GB"的評(píng)論在今天也是錯(cuò)誤的,因?yàn)樗鼈冊(cè)从?code>SHARED_REGION_SIZE_ARM64是
0xa0000000
的時(shí)候。