zoukankan      html  css  js  c++  java
  • 嵌入式 Linux 对内存的直接读写(devmem)

    https://blog.csdn.net/xy010902100449/article/details/47028497
    【摘要】 在Linux开发中着实用到的调试工具并不是很多。devmem的方式是提供给驱动开发人员,在应用层能够侦测内存地址中的数据变化,以此来检测驱动中对内存或者相关配置的正确性验证。

    http://blog.csdn.net/hens007/article/details/7268447

    这个工具的原理也比较简单,就是应用程序通过mmap函数实现对/dev/mem驱动中mmap方法的使用,映射了设备的内存到用户空间,实现对这些物理地址的读写操作。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <ctype.h>
    #include <termios.h>
    #include <sys/types.h>
    #include <sys/mman.h>

    #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s] ",
    __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)

    #define MAP_SIZE 4096UL
    #define MAP_MASK (MAP_SIZE - 1)

    int main(int argc, char **argv) {
    int fd;
    void *map_base, *virt_addr;
    unsigned long read_result, writeval;
    off_t target;
    int access_type = 'w';

    if(argc < 2) {//若参数个数少于两个则打印此工具的使用方法
    fprintf(stderr, " Usage: %s { address } [ type [ data ] ] "
    " address : memory address to act upon "
    " type : access operation type : [b]yte, [h]alfword, [w]ord "
    " data : data to be written ",
    argv[0]);
    exit(1);
    }
    target = strtoul(argv[1], 0, 0);

    if(argc > 2)
    access_type = tolower(argv[2][0]);


    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    printf("/dev/mem opened. ");
    fflush(stdout);

    /* Map one page */ //将内核空间映射到用户空间
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
    if(map_base == (void *) -1) FATAL;
    printf("Memory mapped at address %p. ", map_base);
    fflush(stdout);

    virt_addr = map_base + (target & MAP_MASK);
    //针对不同的参数获取不同类型内存数据
    &nbsp; switch(access_type) {
    case 'b':
    read_result = *((unsigned char *) virt_addr);
    break;
    case 'h':
    read_result = *((unsigned short *) virt_addr);
    break;
    case 'w':
    read_result = *((unsigned long *) virt_addr);
    break;
    default:
    fprintf(stderr, "Illegal data type '%c'. ", access_type);
    exit(2);
    }
    printf("Value at address 0x%X (%p): 0x%X ", target, virt_addr, read_result);
    fflush(stdout);
    //若参数大于3个,则说明为写入操作,针对不同参数写入不同类型的数据
    if(argc > 3) {
    writeval = strtoul(argv[3], 0, 0);
    switch(access_type) {
    case 'b':
    *((unsigned char *) virt_addr) = writeval;
    read_result = *((unsigned char *) virt_addr);
    break;
    case 'h':
    *((unsigned short *) virt_addr) = writeval;
    read_result = *((unsigned short *) virt_addr);
    break;
    case 'w':
    *((unsigned long *) virt_addr) = writeval;
    read_result = *((unsigned long *) virt_addr);
    break;
    }
    printf("Written 0x%X; readback 0x%X ", writeval, read_result);
    fflush(stdout);
    }

    if(munmap(map_base, MAP_SIZE) == -1) FATAL;
    close(fd);
    return 0;
    }

    memdev:直接读写内存。
    可以在busybox的杂项中找到:

    CONFIG_USER_BUSYBOX_DEVMEM:

    devmem is a small program that reads and writes from physical
    memory using /dev/mem.

    Symbol: USER_BUSYBOX_DEVMEM [=y]
    Prompt: devmem
    Defined at ../user/busybox/busybox-1.14.3/miscutils/Kconfig:216
    Depends on: USER_BUSYBOX_BUSYBOX
    Location:
    -> BusyBox (USER_BUSYBOX_BUSYBOX [=y])
    -> Miscellaneous Utilities

    [用法]
    Usage: devmem ADDRESS [WIDTH [VALUE]]
    读取:在地址0x97000000读取32bit值(WIDTH默认等于32, 可选值为[8, 16, 32, 64])
    /dev # devmem 0x97000000
    0x11111111
    读取:在地址0x97000000读取16bit值
    /dev # devmem 0x97000000 16
    0x1111

    写入:在地址0x97000000写入32bit值0x7777ABCD
    /dev # devmem 0x97000000 32 0x7777ABCD
    /dev # devmem 0x97000000
    0x7777ABCD

    注意:如果/dev下没有mem这个node,会出现错误:
    /dev # devmem 0x97000000
    devmem: can't open '/dev/mem': No such file or directory

    这时可以在Host系统中手动创建一个(例如在NFS root filesystem模式):
    host@host-laptop:~/embedded/tftpboot/nfsroot/dev$ sudo mknod mem -m666 c 1 1
    注意这里的权限是666,允许任何人任意读写,可以很好的配合程序debug。

    /dev # devmem 0x97000000
    0x7777ABCD
    ---------------------
    作者:狂奔的乌龟
    来源:CSDN
    原文:https://blog.csdn.net/xy010902100449/article/details/47028497
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    H3C利用dhcp snooping来禁用某个端口下的DHCP
    onu侧各种pon协议下的技术参数10G
    常见Intel网卡芯片对比,多队列网卡介绍
    esxi6.7 7.0 diy for nvme drivers
    Windows Server 2019 OVF 模板下载
    vSphere 6.5支持512e,NVMe SSD呢?
    何时使用领域驱动设计
    徒手打造基于Spark的数据工厂(Data Factory):从设计到实现
    早产的《HelloGitHub》第 65 期
    最简单的人工神经网络
  • 原文地址:https://www.cnblogs.com/Ph-one/p/10209472.html
Copyright © 2011-2022 走看看