• arm_linux_device_mem内存映射 分类: arm-linux-Ubuntu 2013-08-17 10:09 707人阅读 评论(0) 收藏


    /dev/mem: 物理内存的全镜像。可以用来访问物理内存。

    /dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。

    /dev/mem 用来访问物理IO设备�比如X用来访问显卡的物理内存�或嵌入式中访问GPIO。用

    法一般就是open�然后mmap�接着可以使用map之后的地址来访问物理内存。这其实就是实现

    用户空间驱动的一种方法。

    /dev/kmem 一般可以用来查看kernel的变量�或者用作rootkit之类的。 通过/dev/mem设备文件和mmap系统调用�可以将线性地址描述的物理内存映射到进程 

    的地址空间�然后就可以直接访问这段内存了。  比如�标准VGA 16色模式的实模式地址是A000:0000�而线性地址则是A0000。设定显 

    存大小为0x10000�则可以如下操作      mem_fd  = open( "/dev/mem", O_RDWR ); 

        vga_mem = mmap( 0, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, 0xA0000 ); 

        close( mem_fd );  然后直接对vga_mem进行访问�就可以了。当然�如果是操作VGA显卡�还要获得I/O 

    端口的访问权限�以便进行直接的I/O操作�用来设置模式/调色板/选择位面等等  在工控领域中还有一种常用的方法�用来在内核和应用程序之间高效传递数据:  1) 假定系统有64M物理内存�则可以通过lilo通知内核只使用63M�而保留1M物理内    存作为数据交换使用(使用 mem=63M 标记)。 

    2) 然后打开/dev/mem设备�并将63M开始的1M地址空间映射到进程的地址空间。 使用/dev/kmem查看kernel变量 从lwn.net学到的

    实例代码如下�

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #include <stdarg.h>

    #include <fcntl.h>

    #include <unistd.h>

    #include <errno.h> #include <sys/types.h>

    #include <sys/stat.h>

    #include <sys/poll.h>

    #include <sys/mman.h> int page_size;

    #define PAGE_SIZE page_size

    #define PAGE_MASK (~(PAGE_SIZE-1)) void get_var (unsigned long addr) {

            off_t ptr = addr & ~(PAGE_MASK);

            off_t offset = addr & PAGE_MASK;

            int i = 0;

            char *map;

            static int kfd = -1;         kfd = open("/dev/kmem",O_RDONLY);

            if (kfd < 0) {

                    perror("open");                 exit(0);

            }         map = mmap(NULL,PAGE_SIZE,PROT_READ,MAP_SHARED,kfd,offset);         if (map == MAP_FAILED) {

                    perror("mmap");

                    exit(-1);

            }

            /* 假定这里是字符串 */

            printf("%s ",map+ptr);         return;

    } int main(int argc, char **argv) {

            FILE *fp;

            char addr_str[11]="0x";

            char var[51];

            unsigned long addr;

            char ch;

            int r;

            if (argc != 2) {

                    fprintf(stderr,"usage: %s System.map ",argv[0]);

                    exit(-1);

            }         if ((fp = fopen(argv[1],"r")) == NULL) {

                    perror("fopen");

                    exit(-1);

            }         do {

                    r = fscanf(fp,"%8s %c %50s ",&addr_str[2],&ch,var);

                    if (strcmp(var,"modprobe_path")==0)

                            break;

            } while(r > 0);

            if (r < 0) {

                    printf("could not find modprobe_path ");

                    exit(-1);

            }

            page_size = getpagesize();

            addr = strtoul(addr_str,NULL,16);

            printf("found modprobe_path at (%s) %08lx ",addr_str,addr);

            get_var(addr);

    } 运行� # ./tmap /boot/System.map

    found modprobe_path at (0xc03aa900) c03aa900 /sbin/modprobe

    区别�

    1. /dev/mem: 物理内存的全镜像。可以用来访问物理内存。 

    2. /dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的

    内容。

    作用�

    1. 前者用来访问物理IO设备�比如X用来访问显卡的物理内存�或嵌入式

    中访问GPIO。用法一般就是open�然后mmap�接着可以使用map之后的

    地址来访问物理内存。这其实就是实现用户空间驱动的一种方法。 

    2. 后者一般可以用来查看kernel的变量�或者用作rootkit之类的。参考

    1和2描述了用来查看kernel变量这个问题。

    参考�

    1. http://lwn.net/Articles/147902/ 

    2. http://lkml.org/lkml/2005/8/11/301

    LINUX 

    在2.4�可以直接打开/dev/mem�然后读取。

    在2.6�直接打开/dev/mem后�只可以读取前0x101000部分的内容(ubuntu)。

    大约是1MB加4KB。读取后面的内容将出现"open not permitted"错误。

    解决的方法是使用mmap()。routine如下�

    f = open("/dev/mem", O_RDONLY);

    my_mem = mmap (0, 0x1000, PROT_READ, MAP_SHARED, f, 0x34f000);

    if (my_mem == MAP_FAILED)

    printf("map failed %s ",strerror(errno));

    通过my_mem就可以得到0x101000之后的内存内容了 

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

  • 相关阅读:
    js es6遍历对象的6种方法
    MySQL、Redis、MongoDB网络抓包工具
    SSE图像算法优化系列三十一:Base64编码和解码算法的指令集优化(C#自带函数的3到4倍速度)。
    设置EntityFramework中decimal类型数据精度问题(EF默认将只会保留到2为精度)
    IIS资料
    RabbitMQ
    微信公众平台生成带场景参数二维码
    .net Core资料
    微信字体放大影响布局的处理
    VirtualBox虚拟机下安装Win10性能优化
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706840.html
Copyright © 2020-2023  润新知