转自: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. Redis 基础:Redis 事件处理

    Redis 事件处理 Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与客户端(或其他Redis服务器)进行连接,而文件事 ...

  2. Java8 新特性Stream 的学习和使用方法

    流(Stream) 流是java 8 中新引入的特性,用来处理集合中的数据,Stream 是一个来自数据源的元素队列并支持聚合操作. Java 中 Stream 不会存储元素. 数据源 流的来源. 可 ...

  3. TJOI2013数字根

    题面链接 洛谷 sol 我们先不考虑\(0\),发现数字根\(=\)它\(mod 9\). 我们前缀和一波,把区间和变成两数相减. 对于每个\(v\in\{0-8\}\),(这里面的\(mod 9=0 ...

  4. dp的一些计划

    抱歉这是鸽子贴. 树形dp [x][[POI2014]HOT-Hotels](https://www.luogu.org/problemnew/show/P3565) [x][[HAOI2015]树上 ...

  5. 【NOI 2018】冒泡排序(组合数学)

    题意大概是给定一个长度为$n$的排列$p$,求有多少长度为$n$的排列满足冒泡排序的交换次数为$\frac{1}{2} \sum\limits_{i = 1}^{n}|i - p_{i}|$. 可以发 ...

  6. LINUX内核分析第七周——可执行程序的装载

    一.得到一个可执行程序 1. 预处理.编译.链接 gcc hello.c -o hello.exe gcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤. 预处理 => ...

  7. linux内核分析 第五周 扒开系统调用的三层皮(下)

    rm menu -rf 强制删除原menu文件 git clone http://github.com/mengning/menu.git 从github中克隆 cd menu 在test.c中增加上 ...

  8. Android系统权限和root权限

    Android系统权限和root权限http://www.verydemo.com/demo_c189_i277.html

  9. 解题:POI 2008 Plot purchase

    题面 原来看过然后没做,结果板板把这道题改了改考掉了,血亏=.= 首先看看有没有符合条件的点.如果没有开始寻找解,先把所有的大于$2*k$的点设为坏点,然后求最大子矩形,只要一个最大子矩形的权值和超过 ...

  10. 《剑指offer》— JavaScript(15)反转链表

    反转链表 题目描述 输入一个链表,反转链表后,输出链表的所有元素. *** 思路 (本题链表默认无头结点) pHead为当前结点,如果当前结点为空的话,直接返回: pHead为当前结点,pre为当前结 ...