设为首页 加入收藏

TOP

从 Java9 共享内存加载 modules 说起(二)
2018-03-05 08:43:32 】 浏览:607
Tags:Java9 共享 内存 加载 modules 说起
fd file descriptor to an open /proc/pid/pagemap file * @param[in] vaddr virtual address to get entry for * @return 0 for success, 1 for failure */ int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) { size_t nread; ssize_t ret; uint64_t data; nread = 0; while (nread < sizeof(data)) { ret = pread(pagemap_fd, &data, sizeof(data), (vaddr / sysconf(_SC_PAGE_SIZE)) * sizeof(data) + nread); nread += ret; if (ret <= 0) { return 1; } } entry->pfn = data & (((uint64_t)1 << 54) - 1); entry->soft_dirty = (data >> 54) & 1; entry->file_page = (data >> 61) & 1; entry->swapped = (data >> 62) & 1; entry->present = (data >> 63) & 1; return 0; } /* Convert the given virtual address to physical using /proc/PID/pagemap. * * @param[out] paddr physical address * @param[in] pid process to convert for * @param[in] vaddr virtual address to get entry for * @return 0 for success, 1 for failure */ int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr) { char pagemap_file[BUFSIZ]; int pagemap_fd; snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%ju/pagemap", (uintmax_t)pid); pagemap_fd = open(pagemap_file, O_RDONLY); if (pagemap_fd < 0) { return 1; } PagemapEntry entry; if (pagemap_get_entry(&entry, pagemap_fd, vaddr)) { return 1; } close(pagemap_fd); *paddr = (entry.pfn * sysconf(_SC_PAGE_SIZE)) + (vaddr % sysconf(_SC_PAGE_SIZE)); return 0; } int main(int argc, char ** argv){ char *end; int pid; uintptr_t virt_addr; uintptr_t paddr; int return_code; pid = strtol(argv[1],&end, 10); virt_addr = strtol(argv[2], NULL, 16); return_code = virt_to_phys_user(&paddr, pid, virt_addr); if(return_code == 0) printf("Vaddr: 0x%lx, paddr: 0x%lx \n", virt_addr, paddr); else printf("error\n"); }

另外,收集到一些可以读取pagemap信息的工具:

检查两个jvm进程是否映射modules的物理地址一致

  1. 先启动两个jshell
    $ jps 
    25105 jdk.internal.jshell.tool.JShellToolProvider 
    25142 jdk.internal.jshell.tool.JShellToolProvider
  2. 把上面转换地址的代码保存为mymap.c,再编绎
    gcc mymap.c -o mymap
  3. 获取两个jvm的modules的虚拟地址,并转换为物理地址、、
$ pmap -x 25105 | grep modules
00007f82b4b43000  185076    9880       0 r--s- modules
$ sudo ./mymap 25105 00007f82b4b43000
Vaddr: 0x7f82b4b43000, paddr: 0x33598000

$ pmap -x 25142 | grep modules
00007ff220504000  185076   10064       0 r--s- modules
$ sudo ./mymap 25142 00007ff220504000
Vaddr: 0x7ff220504000, paddr: 0x33598000

可以看到两个jvm进程映射modules的物理地址是一样的,证实了最开始的想法。

kernel 里的 page-types 工具

其实在kernel里自带有一个工具page-types可以输出一个page信息,可以通过下面的方式来获取内核源码,然后自己编绎:

sudo apt-get source linux-image-$(uname -r)
sudo apt-get build-dep linux-image-$(uname -r)

tools/vm目录下面,可以直接sudo make编绎。

sudo ./page-types -p 25105
             flags  page-count       MB  symbolic-flags         long-symbolic-flags
0x0000000000000000           2        0  ____________________________________
0x0000000000400000       14819       57  ______________________t_____________   thp
0x0000000000000800           1        0  ___________M________________________   mmap
0x0000000000000828          33        0  ___U_l_____M________________________   uptodate,lru,mmap
0x000000000000086c         663        2  __RU_lA____M________________________   referenced,uptodate,lru,active,mmap
0x000000000000087c           2        0  __RUDlA
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇侦探剧场:堆内存神秘溢出事件 下一篇Dockerfile : tomcat 镜像编写

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目