/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\n",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\n",argv[0]);
} if ((fp = fopen(argv[1],"r")) == null) {
perror("fopen");
} do {
r = fscanf(fp,"%8s %c %50s\n",&addr_str[2],&ch,var);
if (strcmp(var,"modprobe_path")==0)
break;
} while(r > 0);
if (r < 0) {
printf("could not find modprobe_path\n");
page_size = getpagesize();
addr = strtoul(addr_str,null,16);
printf("found modprobe_path at (%s) %08lx\n",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變量這個問題。
參考
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\n",strerror(errno));
通過my_mem就可以得到0x101000之後的記憶體内容了