今天分享一個內核調試實用工具——devmem。
相信很多做底層驅動的人都會經常用到。
什么是devmem?
在Linux系統,如果我們想要訪問某個寄存器,就需要寫一個驅動程序,在驅動中映射寄存器地址,轉為虛擬地址后就可以訪問。
但有時候,我們只是單純想知道某個寄存器的值,不想這么麻煩,怎么辦呢?
Linux早就想到這一點了,于是提供了一個工具devmem,通過devmem就可以直接讀寫寄存器,
devmem是一個命令,在shell中輸入devmem命令就可以非常方便的讀寫寄存器。
如何使用devmem?
devmem命令格式:
Usage:?devmem?ADDRESS?[WIDTH?[VALUE]]Read/write?from?physical?addressADDRESS?Address?to?act?uponWIDTH?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就可以輕松訪問寄存器。
內核配置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 0x40000000int 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,方便我們調試。