不過iOS SDK文檔里並沒有提及這種底層的API,於是我搜了一番,找到了 host_statistics() 這個函數。
參數雖然很多,但基本上都是固定的值,我也就不解釋,直接上代碼了:
#include <mach/mach.h>
BOOL memoryInfo(vm_statistics_data_t *vmStats) {
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)vmStats, &infoCount);
return kernReturn == KERN_SUCCESS;
}
void logMemoryInfo() {
vm_statistics_data_t vmStats;
if (memoryInfo(&vmStats)) {
NSLog( @" free: %u\nactive: %u\ninactive: %u\nwire: %u\nzero fill: %u\nreactivations: %u\npageins: %u\npageouts: %u\nfaults: %u\ncow_faults: %u\nlookups: %u\nhits: %u ",
vmStats.free_count * vm_page_size,
vmStats.active_count * vm_page_size,
vmStats.inactive_count * vm_page_size,
vmStats.wire_count * vm_page_size,
vmStats.zero_fill_count * vm_page_size,
vmStats.reactivations * vm_page_size,
vmStats.pageins * vm_page_size,
vmStats.pageouts * vm_page_size,
vmStats.faults,
vmStats.cow_faults,
vmStats.lookups,
vmStats.hits
);
}
}
BOOL memoryInfo(vm_statistics_data_t *vmStats) {
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)vmStats, &infoCount);
return kernReturn == KERN_SUCCESS;
}
void logMemoryInfo() {
vm_statistics_data_t vmStats;
if (memoryInfo(&vmStats)) {
NSLog( @" free: %u\nactive: %u\ninactive: %u\nwire: %u\nzero fill: %u\nreactivations: %u\npageins: %u\npageouts: %u\nfaults: %u\ncow_faults: %u\nlookups: %u\nhits: %u ",
vmStats.free_count * vm_page_size,
vmStats.active_count * vm_page_size,
vmStats.inactive_count * vm_page_size,
vmStats.wire_count * vm_page_size,
vmStats.zero_fill_count * vm_page_size,
vmStats.reactivations * vm_page_size,
vmStats.pageins * vm_page_size,
vmStats.pageouts * vm_page_size,
vmStats.faults,
vmStats.cow_faults,
vmStats.lookups,
vmStats.hits
);
}
}
調用memoryInfo()就能拿到內存信息了,它的類型是 vm_statistics_data_t 。這個結構體有很多字段,在logMemoryInfo()中展示了如何獲取它們。注意這些字段大都是頁面數,要乘以vm_page_size才能拿到字節數。
順便再簡要介紹下:free是空閑內存;active是已使用,但可被分頁的(在iOS中,只有在磁盤上靜態存在的才能被分頁,例如文件的內存映射,而動態分配的內存是不能被分頁的);inactive是不活躍的,也就是程序退出后卻沒釋放的內存,以便加快再次啟動,而當內存不足時,就會被回收,因此也可看作空閑內存;wire就是已使用,且不可被分頁的。此外,這篇 文檔 也有作介紹。
最后你會發現,即使把這些全加起來,也比設備內存少很多,那么剩下的只好當成已被占用的神秘內存了。不過在模擬器上,這4個加起來基本上就是Mac的物理內存量了,相差不到2MB。
而總物理內存可以用NSRealMemoryAvailable()來獲取,這個函數不需要提供參數,文檔里也有記載,我就不寫演示代碼了。
