内核调试之devmem直接读写寄存器

本文介绍了Linux内核调试工具devmem的使用方法,包括如何直接读写物理地址的寄存器,以及内核配置中启用/dev/mem的步骤。此外,还展示了在Linux应用层实现类似devmem功能的代码示例,便于驱动开发者进行底层调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


今天分享一个内核调试实用工具——devmem。

相信很多做底层驱动的人都会经常用到。

什么是devmem?

在Linux系统,如果我们想要访问某个寄存器,就需要写一个驱动程序,在驱动中映射寄存器地址,转为虚拟地址后就可以访问。

但有时候,我们只是单纯想知道某个寄存器的值,不想这么麻烦,怎么办呢?

Linux早就想到这一点了,于是提供了一个工具devmem,通过devmem就可以直接读写寄存器,

devmem是一个命令,在shell中输入devmem命令就可以非常方便的读写寄存器。

如何使用devmem?

devmem命令格式:

Usage: devmem ADDRESS [WIDTH [VALUE]]

Read/write from physical address

	ADDRESS	Address to act upon
	WIDTH	Width (8/16/...)
	VALUE	Data to be written

ADDRESS:物理地址

WIDTH:位宽,32位、64位等等

VALUE:要写入的值

例如,读取32位0x40200000寄存器的值:

devmem 0x40200000 32

向32位0x40200000寄存器写入0x12345678

devmem 0x40200000 32 0x12345678

内核配置devmem

devmem命令依赖于/dev/mem设备节点,需要在Linux内核中打开/dev/mem的配置:

Device Drivers  --->
	Character devices  --->
		[*] /dev/mem virtual device support

在这里插入图片描述

Linux应用层操作寄存器

除了直接使用devmem,我们也可以在Linux应用层自己实现一个devmem。

devmem的实现原理,就是打开/dev/mem,然后通过mmap映射物理地址,从而实现读写寄存器。因此,我们只要实现这些操作,就可以自己实现类似devmem的功能。

例如,在Linux应用层读取物理地址为0x40000000的值:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define MAP_SIZE 0x80000
#define base 0x40000000

int main(int argc, char **argv)
{
	int fd = open("/dev/mem",O_RDWR|O_NDELAY);
    
    if (fd < 0)
    {
        printf("open /dev/mem error!\n");
        return -1;
	}
    
    void *map_base = mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,base);
    if (map_base == MAP_FAILED)
  		return -1;
    
    printf("%x \n",*(volatile unsigned int*)(map_base));

    close(fd);
    munmap(map_base,MAP_SIZE);
    
	return 0;
}

总结

devmem是一个很常用的工具,主要给驱动开发人员在Linux应用层调试使用。devmem不仅仅是访问寄存器,只要有权限访问某个物理地址,就可以使用devmem,方便我们调试。

原文链接: 内核调试之devmem直接读写寄存器

<think>好的,我现在需要帮助用户解决如何使用devmem工具批量读取内存地址的问题。首先,我得回忆一下devmem的基本用法和相关知识。根据用户提供的引用内容,特别是引用[1]和[3],devmem是通过mmap映射物理地址到用户空间,允许直接读写内存。基本命令格式是`devmem ADDRESS [WIDTH [VALUE]]`,其中ADDRESS是物理地址,WIDTH是数据宽度,默认32位,VALUE是要写入的值,如果不写VALUE则是读取。 用户的需求是批量读取多个内存地址的值,而devmem本身每次只能处理一个地址。所以需要想办法循环调用devmem或者编写脚本。首先想到的是使用Shell脚本,比如for循环遍历地址列表。例如,可以写一个脚本,循环读取从起始地址开始,按偏移量递增的多个地址。或者用户可能有特定的地址列表,每个地址都需要单独读取。 接下来,我需要考虑如何构造这样的脚本。比如,如果用户要读取0x97000000到0x9700000F之间的每个32位地址,可以用seq生成地址序列,然后逐个调用devmem。或者用C语言写一个程序,直接调用mmap,这样效率更高,但可能用户更倾向于使用现有的工具如devmem结合脚本。 另外,引用[4]提到devmem常用于驱动调试直接操作物理地址,但需要注意安全性,因为错误操作可能导致系统崩溃。在批量读取时,尤其要确保地址范围是合法的,避免访问受限区域。 可能的问题包括:如何传递多个地址给devmem,如何处理不同的数据宽度,以及如何格式化输出以便用户查看。还需要注意权限问题,可能需要root权限执行devmem。 可能的解决方案是编写一个Shell脚本,读取一个地址列表文件,逐行调用devmem,并将结果保存到文件。或者使用awk、xargs等工具批量处理。此外,如果地址连续,可以用循环结构自动递增地址值。 最后,要提醒用户谨慎操作,确保地址有效,并考虑使用后台执行或日志记录,特别是在大量读取时。总结步骤应该是:确定地址列表,编写脚本循环调用devmem,处理输出,注意事项。</think>### 分步说明:使用devmem批量读取内存地址 #### 方法1:Shell脚本循环读取(适用于连续地址) ```bash #!/bin/bash BASE_ADDR=0x97000000 # 起始地址 COUNT=10 # 读取次数 WIDTH=32 # 数据宽度(8/16/32/64) for ((i=0; i<COUNT; i++)) do ADDR=$(printf "0x%X" $((BASE_ADDR + i*4))) # 地址按4字节递增(32位宽度) VALUE=$(devmem $ADDR $WIDTH) echo "Address: $ADDR => Value: $VALUE" done ``` **说明**: - 通过`BASE_ADDR`设置起始物理地址,`COUNT`控制读取次数 - `i*4`表示每次地址递增4字节(对应32位宽度),若使用16位则改为`i*2` - 输出格式为`Address: 0x... => Value: 0x...` #### 方法2:从文件读取离散地址(适用于非连续地址) 1. 创建地址列表文件`addr_list.txt`: ``` 0x97000000 0x97000010 0x97000020 ``` 2. 编写脚本: ```bash #!/bin/bash WIDTH=32 while read ADDR do VALUE=$(devmem $ADDR $WIDTH 2>/dev/null) echo "$ADDR: $VALUE" done < addr_list.txt ``` #### 方法3:使用xargs单行命令 ```bash echo -e "0x97000000\n0x97000004" | xargs -I{} devmem {} 32 ``` #### 注意事项 1. **权限要求**:必须使用`sudo`或以root用户执行[^1][^3] 2. **地址有效性**:避免访问保留内存区域(如MMIO寄存器)导致系统崩溃[^4] 3. **性能优化**:连续读取时建议使用C语言直接调用`mmap`(参考引用[1]原理) ```c int fd = open("/dev/mem", O_RDWR); void *map = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, base_addr); ``` 4. **错误处理**:添加`2>/dev/null`可屏蔽权限错误提示 #### 扩展应用 通过`awk`实现十六进制转换: ```bash devmem 0x97000000 32 | awk '{printf "DEC: %d\nHEX: 0x%X\n", $1, $1}' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式Linux充电站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值