zoukankan      html  css  js  c++  java
  • 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之后的内存内容了 

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

  • 相关阅读:
    生成随机《c和指针笔记》让rand更随机一点
    mvcframeworkProgramming ASP.NET MVCFundamentals of ASP.NET MVC(四)Controller
    直线距离uva 11168 Airport(训练指南)
    分量算法poj 1751 Highways 最小生成树之Kruskal(克鲁斯卡尔)算法
    图片对象android学习笔记之使用ClipDrawable
    汇总窗口Visual Studio Watch 窗口技巧汇总
    百度用户百度,来一场华丽的视觉盛宴吧
    Dynamic 动态类型 和双问号??的使用
    C# insert into 一条记录后获取该记录的自动增长列ID
    MVC JsonResult的使用
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706840.html
Copyright © 2011-2022 走看看