在运行Linux的基于ARM的系统上,我有一个内存映射到物理地址的设备.从所有地址都是虚拟的用户空间程序,我如何从该地址读取内容?
我有Linux,我有一个物理地址:(即0x60000000).
我想从用户空间Linux程序中读取此地址.
该地址可能位于内核空间中.
对于两个进程A和B,两者都使用库libc.so,libc.so只加载到内存中一次.当A和B都在同一主机和相同的rootfs上运行时,这是正常情况.
对于容器,如果A和B在不同的容器中运行,A和B是否共享相同的内存区域?
例如
imageA
--libc.so
--programA
imageB
--libc.so
--programB
我们使用chroot在不同的rootfs中运行A和B. 两个libc.so是一样的.libc.so会被加载到内存中两次吗?
我试图了解标题中提到的两个文件.我抬头看了些什么东西; 但是,我无法理解如何从中提取有用的信息(或者我只是以错误的方式接近它).
让我解释一下:页面映射是一个相当新的"特征"伪文件,它包含分配给当前[pid]的虚拟页面的物理帧信息.也就是说,给定一个从地址x开始的虚拟页面,比如用于虚拟地址开始的'vas',我可以使用vas索引页面映射文件以获得映射的物理页面帧的64位.这些位包含有关该虚拟页面的信息.然而,当我提取位并进行一些移动时,我迷失了我所看到的东西.
这些位表示如下:0-54是页面帧号,55-60是页面移位,第63位是当前位,还有其他位对我不感兴趣.在我使用/ proc/[pid]/maps中的vas地址进行一些映射之后,似乎几乎每个进程的页面都被交换,即第63位始终为零.:(
我想问题是,如何有效地使用页面地图获取/ proc/[pid]/maps给出的地址的等效物理地址
公平地说,我发布了一个类似的问题,但几天前的方法有点不同.
如果有人能够对这个问题有所了解,我将非常感激.
===编辑===
要解决以下评论:我正在从/ proc/[pid]/maps读取一行,其行如下所示:
00400000-00401000 r-xp 00000000 08:01 8915461/home/janjust/my_programs/shared_mem 7ffffef1b000-7ffffef3c000 rw -p 00000000 00:00 0 [stack]
然后我将提取它接触的虚拟页面的数量并索引二进制文件/ proc/[pid]/pagemaps,并且对于每个虚拟页面,我可以提取它分配给它的物理页面.
输出如下:
00400000-00401000 r-xp 00000000 08:01 8915461/home/janjust/my_programs/shared_mem num_pages:1:86000000001464C6
虚拟范围中每个虚拟页面的一个物理地址.
读取行和提取物理地址的代码是:
74 /* process /proc/pid/maps, by line*/
75 while(fgets(line, 256, in_map) != NULL){
76 unsigned long vas;
77 unsigned long vae;
78 int num_pages;
79
80 //print line
81 printf("%s", line);
82
83 /*scan for the virtual addresses*/
84 n = sscanf(line, "%lX-%lX", &vas, &vae);
85 …
Run Code Online (Sandbox Code Playgroud) 我试图破译如何使用/ proc/pid/pagemap来获取给定页面集的物理地址.假设从/ proc/pid/maps,我得到对应堆的虚拟地址afa2d000-afa42000.我的问题是如何使用此信息遍历页面映射文件,并找到对应于地址afa2d000-afa42000的物理页面框架.
/ proc/pid/pagemap条目采用二进制格式.有没有工具可以帮助解析这个文件?
除了手动浏览页面目录条目外,有没有合适的方法来获取逻辑地址的物理地址?我在内核的源代码中寻找了这个功能,并发现有一个follow_page
功能可以很好地利用内置的巨大且透明的大页面支持.但是它没有导出到内核模块(为什么???)......
因此,我不想发明轮子,我认为follow_page
手动重新实现功能并不是很好.
我正在尝试在Linux上创建自己的proc节点"os_pagemap"(使用odroid)
该节点的目标是打印所有物理内存页面的信息.(sudo cat/proc/os_pagemap)
像这样 :
[PHY] Virt 483252 Phy 266908 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483253 Phy 266909 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483254 Phy 266910 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 398391 Phy 266920 VMA /dev/ashmem/dalvik-bitmap-1 PID 5773 PNAME com.sec.android.app.keyboard
Run Code Online (Sandbox Code Playgroud)
其中VMA是指VMA名称
为了实现目标,我的设计是这样的:
1. read_lock(&tasklock)
2. for_each_process(p) => get pids
3. read_unlock(&tasklock)
4. Loop for each pid
1)task = get_pid_task(pid)
2)if task==NULL => skip
3)mm=task->mm
4)down_read(&mm->mmap_sem)
5)Loop for each vma in mm …
Run Code Online (Sandbox Code Playgroud) Linux 可以同时拥有标准 4KiB 页面内存和 1GiB(巨大)页面内存(以及 2MiB 页面,但我不知道是否有人使用它)。
是否有从任意虚拟地址获取页面大小的标准调用?指针可能指向 4K 页或大页。
手头的问题是对assert(...)
需要基地址和区域大小必须是页面大小的倍数的函数的参数进行健全 ( ) 检查,然后传递给mbind
. 但是页面大小因系统而异。如果没有健全性检查,mbind
只给出的返回值Invalid argument
对调试没有帮助。
我看过这个答案How to get linux kernel page size programmatically但它给出的答案假设整个系统是相同的,而且它们也是编译时常量。也getpagesize()
做同样的事情,无论如何它都被弃用了。