如何编译devmem_devmem读写物理内存和devkmem读取内核虚拟内存

关键词:/dev/mem、/dev/kmem、mmap、__va、__pa、remap_pfn_range等等。在日常工作中常有直接操作寄存器或者某一物理地址的需求,busybox中提供了devmem。通过它可以读写物理内存。它的实现借助mmap和/dev/mem,通过mmap将/dev/mem物理地址映射到用户空间,devmem就可以像操作虚拟地址一样进行读写。hexdump同样也可以类似dev...
摘要由CSDN通过智能技术生成

关键词:/dev/mem、/dev/kmem、mmap、__va、__pa、remap_pfn_range等等。

在日常工作中常有直接操作寄存器或者某一物理地址的需求,busybox中提供了devmem。通过它可以读写物理内存。

它的实现借助mmap和/dev/mem,通过mmap将/dev/mem物理地址映射到用户空间,devmem就可以像操作虚拟地址一样进行读写。

hexdump同样也可以类似devmem的功能。

如果需要在用户空间获取内核某个变量值,可以使用devkmem通过/dev/kmem进行。

下面分别介绍这三种工具。

1. devmem操作物理地址,它是如何做到的?

用户空间是无法直接操作物理地址的;但是日常工作中常需要对某一物理地址进行读写,尤其是寄存器。

devmem可以实现这个功能。那么devmem做了什么?/dev/mem在内核中优势如何实现的呢?

1.1 devmem工具使用

devmem使用介绍如下:

BusyBox v1.27.2 (2019-04-16 17:00:28 CST) multi-call binary.

Usage: devmem ADDRESS [WIDTH [VALUE]]

Read/write fromphysical address

ADDRESS Address to act upon

WIDTH Width (8/16/...)

VALUE Data to be written

devmem的能力有限,只能处理最大64字节的数目。

下面向0xfc20700这个地址写入32位数据0x12345678:

devmem 0xfc20700 32 0x12345678

然后从0xfc20700读取进行验证。

devmem 0xfc20700 32

0x12345678

1.2 devmem工具分析

从下面的代码可知,devmem解析参数,然后将地址转换成页面对齐的地址。mmap将/dev/mem的输入地址偏移的页面映射到用户空间,然后读取数值。

int devmem_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;int devmem_main(int argc UNUSED_PARAM, char **argv)

{void *map_base, *virt_addr;

uint64_t read_result;

uint64_t writeval= writeval; /*for compiler*/off_t target;

unsigned page_size, mapped_size, offset_in_page;intfd;

unsigned width= 8 * sizeof(int); /*ADDRESS*/

if (!argv[1])

bb_show_usage();

errno= 0;

target= bb_strtoull(argv[1], NULL, 0); /*allows hex, oct etc*/---------------第一个参数是地址

/*WIDTH*/

if (argv[2]) {------------------------------------------------------------------第二个参数,在写的情况下,需要知道写数据的位宽。if (isdigit(argv[2][0]) || argv[2][1])

width= xatou(argv[2]);else{static const char bhwl[] ALIGN1 = "bhwl";static const uint8_t sizes[] ALIGN1 ={8 * sizeof(char),8 * sizeof(short),8 * sizeof(int),8 * sizeof(long),0 /*bad*/};

width= strchrnul(bhwl, (argv[2][0] | 0x20)) -bhwl;

width=sizes[width];

}/*VALUE*/

if (argv[3])-----------------------------------------------------------------第三个参数,待写入数值。

writeval= bb_strtoull(argv[3], NULL, 0);

}else { /*argv[2] == NULL*/

/*make argv[3] to be a valid thing to fetch*/argv--;

}if(errno)

bb_show_usage();/*one of bb_strtouXX failed*/fd= xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY |O_SYNC));-------根据第三个参数确定是以只读形式打开,还是以读写形式打开。/dev/mem代表整个内核空间。

mapped_size= page_size =getpagesize();

offset_in_page= (unsigned)target & (page_size - 1);-----------------------------对地址进行也对齐。if (offset_in_page + width >page_size) {----------------------------------------如果跨页,则mapped_size变成两个页面。/*This access spans pages.

* Must map two pages to make it possible:*/mapped_size*= 2;

}

map_base=mmap(NULL,

mapped_size,

argv[3] ? (PROT_READ |PROT_WRITE) : PROT_READ,

MAP_SHARED,

fd,

target& ~(off_t)(page_size - 1));---------------------------------------将/dev/mem文件的从target的页对齐偏移开始,映射mapped_size块大小内存。映射结果是map_base。if (map_base ==MAP_FAILED)

bb_perror_msg_and_die("mmap");//printf("Memory mapped at address %p.\n", map_base);

virt_addr= (char*)map_base +offset_in_page;if (!argv[3]) {switch(width) {case 8:

read_result= *(volatile uint8_t*)virt_addr;break;case 16:

read_result= *(volatile uint16_t*)virt_addr;break;case 32:

read_result= *(volatile uint32_t*)virt_addr;break;case 64:

read_result= *(volatile uint64_t*)virt_addr;break;default:

bb_error_msg_and_die("bad width");

}//printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n",//target, virt_addr,//(unsigned long long)read_result);

/*Zero-padded output shows the width of access just done*/printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result);------------读取数据并打印。

}else{switch(width) {case 8:*(volatile uint8_t*)virt_addr =

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值