iOS获取进程虚拟内存区域代码

最近看深入理解计算机系统内存章节部分,看完之后想着实操一下,于是从最熟悉的 macOS/iOS 下手,看一下进程的虚拟内存区域是如何分布的。

直接上代码

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        struct task_basic_info task_basic_info;
        mach_msg_type_number_t size = sizeof(task_basic_info);
        //1. 获取task_info
        kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&task_basic_info, &size);
        if (kerr == KERN_SUCCESS) {
            NSLog(@"%lu",task_basic_info.resident_size);
            NSLog(@"%lu",task_basic_info.virtual_size);
        } else {
            printf(0);
        }
        kern_return_t ret;
        task_t task;
        unsigned int depth = 0;
        uint64 addr = 0;
        int count;
        //1. 拿到当前的任务 #需要通过进程 id 获取
        //2. 获取地址 1 所在的 VMA
        //3. 递归获取进程的 VMA 
        int pid = [[NSProcessInfo processInfo] processIdentifier];
        printf("进程id %d\n", pid);
        uint64 target_addr = 1;
        vm_size_t vm_size = 0;
        vm_region_submap_info_data_64_t info;
        mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
        mach_port_t object_name;
        ret = task_for_pid (mach_task_self(), pid, &task);
        ret = vm_region_64(task, &target_addr, &vm_size, VM_REGION_BASIC_INFO_64, &info, &info_count, &object_name);
        while (ret == KERN_SUCCESS) {
            printf("vma address area [%p-%p] size %d\n ",target_addr, target_addr+vm_size, vm_size);
            target_addr = target_addr + vm_size;
            ret = vm_region_64(task, &target_addr, &vm_size, VM_REGION_BASIC_INFO_64, &info, &info_count, &object_name);
        }
        if (ret != KERN_SUCCESS)
            return 0;
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

对应命令

vmmap [processid]-verbose

参考地址:

  1. 深入解析 MAC OS X & IOS 操作系统 - 11.1 调度原语
  2. 深入解析 MAC OS X & IOS 操作系统 - 12.1 虚拟内存架构