转自:http://blog.csdn.net/kongkongkkk/article/details/74366200

如果让你编写一个程序,来获取虚拟地址对应的物理地址。。你会试着操作MMU吗。。→_→*

    1. Linux文件目录中的/proc记录着当前进程的信息,称其为虚拟文件系统。在/proc下有一个链接目录名为self,这意味着哪一个进程打开了它,self中存储的信息就是所链接进程的。self中有一个名为pagemap的文件,专门用来记录所链接进程的物理页号信息。这样通过/proc/pid/pagemap文件,允许一个用户态的进程查看到每个虚拟页映射到的物理页

    2. /proc/pid/pagemap中的每一项都包含了一个64位的值,这个值内容如下所示。每一项的映射方式不同于真正的虚拟地址映射,其文件中遵循独立的对应关系,即虚拟地址相对于0x0经过的页面数是对应项在文件中的偏移量

      * /proc/pid/pagemap.  This file lets a userspace process find out which
      physical frame each virtual page is mapped to. It contains one 64-bit
      value for each virtual page, containing the following data (from
      fs/proc/task_mmu.c, above pagemap_read): * Bits 0-54 page frame number (PFN) if present//present为1时,bit0-54表示物理页号
      * Bits 0-4 swap type if swapped
      * Bits 5-54 swap offset if swapped
      * Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
      * Bit 56 page exclusively mapped (since 4.2)
      * Bits 57-60 zero
      * Bit 61 page is file-page or shared-anon (since 3.5)
      * Bit 62 page swapped
      * Bit 63 page present//如果为1,表示当前物理页在内存中;为0,表示当前物理页不在内存中
    3. 1在计算物理地址时,只需要

找到虚拟地址的对应项,再通过对应项中的bit63判断此物理页是否在内存中,若在内存中则对应项中的物理页号加上偏移地址,就能得到物理地址

  1. 通过程序获取物理地址并验证写时拷贝技术


    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <stdint.h> //计算虚拟地址对应的地址,传入虚拟地址vaddr,通过paddr传出物理地址
    void mem_addr(unsigned long vaddr, unsigned long *paddr)
    {
    int pageSize = getpagesize();//调用此函数获取系统设定的页面大小 unsigned long v_pageIndex = vaddr / pageSize;//计算此虚拟地址相对于0x0的经过的页面数
    unsigned long v_offset = v_pageIndex * sizeof(uint64_t);//计算在/proc/pid/page_map文件中的偏移量
    unsigned long page_offset = vaddr % pageSize;//计算虚拟地址在页面中的偏移量
    uint64_t item = 0;//存储对应项的值 int fd = open("/proc/self/pagemap", O_RDONLY);。。以只读方式打开/proc/pid/page_map
    if(fd == -1)//判断是否打开失败
    {
    printf("open /proc/self/pagemap error\n");
    return;
    } if(lseek(fd, v_offset, SEEK_SET) == -1)//将游标移动到相应位置,即对应项的起始地址且判断是否移动失败
    {
    printf("sleek error\n");
    return;
    } if(read(fd, &item, sizeof(uint64_t)) != sizeof(uint64_t))//读取对应项的值,并存入item中,且判断读取数据位数是否正确
    {
    printf("read item error\n");
    return;
    } if((((uint64_t)1 << 63) & item) == 0)//判断present是否为0
    {
    printf("page present is 0\n");
    return ;
    } uint64_t phy_pageIndex = (((uint64_t)1 << 55) - 1) & item;//计算物理页号,即取item的bit0-54 *paddr = (phy_pageIndex * pageSize) + page_offset;//再加上页内偏移量就得到了物理地址
    } const int a = 100;//全局常量 int main()
    {
    int b = 100;//局部变量
    static c = 100;//局部静态变量
    const int d = 100;//局部常量
    char *str = "Hello World!"; unsigned long phy = 0;//物理地址 char *p = (char*)malloc(100);//动态内存 int pid = fork();//创建子进程
    if(pid == 0)
    {
    //p[0] = '1';//子进程中修改动态内存
    mem_addr((unsigned long)&a, &phy);
    printf("pid = %d, virtual addr = %x , physical addr = %x\n", getpid(), &a, phy);
    }
    else
    {
    mem_addr((unsigned long)&a, &phy);
    printf("pid = %d, virtual addr = %x , physical addr = %x\n", getpid(), &a, phy);
    } sleep(100);
    free(p);
    waitpid();
    return 0;
    }
  2. 测试结果如下:

    • 全局常量:符合写时拷贝技术

    • 局部变量:不符合写时拷贝技术。原因分析,有可能是物理页上的其他数据被改动,导致拷贝出一个新物理页面

    • 局部静态变量:不符合写时拷贝技术。原因分析,有可能是物理页上的其他数据被改动,导致拷贝出一个新物理页面

    • 局部常量:不符合写时拷贝技术。原因分析,有可能是物理页上的其他数据被改动,导致拷贝出一个新物理页面

    • 字符串:符合写时拷贝技术

    • 动态内存:符合写时拷贝技术
      子进程不修改动态内存

      子进程修改动态内存

*其实想要知道虚拟地址对应的物理地址,通过这样的方式也可以得到物理地址而不用操作MMU。。。*

版权声明:本文为博主kongkongkkk原创文章,未经博主允许不得转载。

Linux下如何在进程中获取虚拟地址对应的物理地址【转】的更多相关文章

  1. linux 下查看某个进程中线程运行在哪个CPU上

    运行程序,使用命令top查看指定的进程的PID: 然后使用命令: top -H -p PID 按f键,并使用上下切换,利用空格键选中nTH,P: 按esc键,P所在的列就是线程运行的CPU号:

  2. Linux 下 expect 脚本语言中交互处理常用命令

    Linux 下 expect 脚本语言中交互处理常用命令 1. #!/usr/bin/expect 告诉操作系统脚本里的代码使用那一个 shell 来执行.这里的 expect 其实和 Linux 下 ...

  3. Linux下查看某个进程打开的文件数-losf工具常用参数介绍

    Linux下查看某个进程打开的文件数-losf工具常用参数介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在linux操作系统中,一切皆文件.通过文件不仅仅可以访问常规数据,还 ...

  4. 解决linux下tomcat停止进程任存在问题

    解决linux下tomcat停止进程任存在问题 在Linux下(之所以强调linux下,是因为在windows下正常),执行tomcat ./shutdown.sh 后,虽然tomcat服务不能正常访 ...

  5. linux下实现监控进程网络带宽

    嗯,近期都在网易游戏实习,所以貌似有段时间没有上来写点东西了... 来网易游戏实习最基本的目的事实上就是想知道在游戏公司里面工作都是些什么内容,毕竟自己曾经也没有接触过游戏公司.. 还比較的好奇.. ...

  6. windows和linux下关闭Tomcat进程

    windows和linux下解决Tomcat进程 windows下启动Tomcat报错,8080端口号被占用,报错信息如下 两种解决方法,一种是关闭了这个端口号,另外一种是修改Tomcat下的serv ...

  7. windows下数据库文件使用脚本同步到linux下的mysql数据库中

    1.背景 windows server 2008 下 每天会有 *.sql数据文件 需要上传到linux 中的mysql数据库中 而运维人员是在 windows server 下使用 xshell 连 ...

  8. linux下,一个运行中的程序,究竟占用了多少内存

    linux下,一个运行中的程序,究竟占用了多少内存 1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中  VSZ(或VSS)列 表示,程序占用 ...

  9. windows和linux下杀死Tomcat进程,解决端口占用

    windows和linux下解决Tomcat进程 windows下启动Tomcat报错,8080端口号被占用,报错信息如下 两种解决方法,一种是关闭了这个端口号,另外一种是修改Tomcat下的serv ...

随机推荐

  1. ajax请求提交到controller后总是不成功

    最近在做实习时,点击查询时在js中发送ajax请求到controller后台,但是无论怎么样都不成功,请求地址是正确的,因为在后台用system.out.println输出有值,并且也确实return ...

  2. 【CF183D】T-shirt(动态规划,贪心)

    [CF183D]T-shirt(动态规划,贪心) 题面 洛谷 CodeForces 题解 \(O(n^2m)\)的暴力懒得写了,比较容易,可以自己想想. 做法是这样的,首先我们发现一个结论: 对于某个 ...

  3. 【AGC003F】Fraction of Fractal

    Description ​ 原题链接 ​ Solution ​ 神题. ​ 定义一个上边界或下边界的格子为"上下接口",当且仅当上下边界该位置的格子都是黑色的. ​ "左 ...

  4. bzoj 4028 : [HEOI2015]公约数数列

    之前看了好几次都没什么思路,今天下定决心把这题切了. 观察到$0-x$的gcd最多变化log次,因为它每次变化一定至少要去掉一个质因子,所以我们可以枚举gcd. 因为数据范围比较小,所以想到了分块. ...

  5. 【agc019F】Yes or No

    Portal -->agc019F Description 给你\(n+m\)个询问,其中\(n\)个的答案是\(Yes\),\(m\)个的答案是\(No\),现在依次回答这些询问,每回答一个询 ...

  6. JavaScript演示下Singleton设计模式

    单例模式的基本结构: MyNamespace.Singleton = function() { return {}; }(); 比如: MyNamespace.Singleton = (functio ...

  7. dingo 内部调用获取异常信息

    $exception->getResponse(); $params = [ 'company_id' => $this->request->input('company_id ...

  8. 3.CentOS的一些小笔记

    1.一般来说,主文件夹都在/home下面,比如登陆的账户为LyndonMario,则我的主文件夹为 /home/LyndonMario. 2.ctrl+space可以调出输入法. 3.CentOS中的 ...

  9. AES-NI指令集

    对于intel的AES-NI新指令集,需要i5处理器及以上的相关硬件支持.在编译时,可能会出现 /usr/lib/gcc/x86_64-linux-gnu/4.8/include/wmmintrin. ...

  10. lower_bound/upper_bound example

    http://www.cplusplus.com/reference/algorithm/upper_bound/左闭右开 Return iterator to lower bound Returns ...