如何使用/ dev / kmem?

更新了我的post…

我得到了程序。 它在/dev/kmem/dev/mem

我想我可以从代码中学到一些东西。 但是当我在Beagle Board上运行的时候,结果如下:

 case 1: ( if(1) ) root@omap:/home/ubuntu/tom# ./kmem_mem /boot/System.map-3.0.4-x3 found jiffies at (0xc0870080) c0870080 /dev/kmem read buf = 319317 jiffies=319317 (read from virtual memory) /dev/mem: the offset is 870080 the page size = 4096 mmap: Invalid argument case 2: ( if(0) ) root@omap:/home/ubuntu/tom# ./kmem_mem /boot/System.map-3.0.4-x3 found jiffies at (0xc0870080) c0870080 /dev/kmem read buf = 333631 jiffies=333631 (read from virtual memory) /dev/mem: the offset is 870080 /dev/mem read failed: Bad address jiffies=0 (read from physical memory) 

我使用下面的命令,以便mmap可以使用NULL作为其第一个参数。

 root@omap:/home/ubuntu/tom# echo 0 > /proc/sys/vm/mmap_min_addr root@omap:/home/ubuntu/tom# cat /proc/sys/vm/mmap_min_addr 0 

正如你所看到的, read_kmem()可以正常工作,但是read_mem()不起作用,看起来转移到它的'偏移'是错误的。 但内核地址 – PAGE_OFFSET(0xC0000000) = physical address ,是不是错误?

我的问题是:(1)为什么在案例1中“mmap:Invalid argument”? (2)为什么mmap只映射PAGE_SIZE长度空间? (3) read_mem什么问题?

谁能帮忙? 谢谢!

 /* * getjiff.c * * this toolkit shows how to get jiffies value from user space: * 1. find jiffies's address from kernel image. * 2. access virtual address space to get jiffies value. * 3. access physical address sapce to get jiffies value. * * demostrate following techniques: * o get ELF object symbol address by calling nlist() * o access virtual memory space from /dev/kmem * o access virtual memory space from /dev/mem */ #include <stdio.h> #include <stdlib.h> //exit #include <linux/a.out.h> //nlist #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <memory.h> #define LONG *(volatile unsigned long*) /* read from virtual memory */ int read_kmem(off_t offset, void* buf, size_t count) { int fd; int n; fd = open("/dev/kmem", O_RDONLY); if (fd < 0) { perror("open /dev/kmem failed"); return -1; } lseek(fd, offset, SEEK_SET); n = read(fd, buf, count); if (n != count) perror("/dev/kmem read failed"); else printf("/dev/kmem read buf = %ld\n", *(unsigned long *)buf); close(fd); return n; } /* read from physical memory */ int read_mem(off_t offset, void* buf, size_t count) { int fd; int n; int page_size; void *map_base; unsigned long value; printf("/dev/mem: the offset is %lx\n", offset); fd = open("/dev/mem", O_RDONLY); if (fd < 0) { perror("open /dev/mem failed"); return -1; } if(1){ page_size = getpagesize(); printf("the page size = %d\n", page_size); map_base = mmap(0,page_size,PROT_READ,MAP_SHARED,fd,offset); if (map_base == MAP_FAILED){ perror("mmap"); exit(1); } value = LONG(map_base); printf("/dev/mem: the value is %ld\n", value); buf = (unsigned long *)map_base; } if(0){ lseek(fd, offset, SEEK_SET); n = read(fd, buf, count); if (n != count) perror("/dev/mem read failed"); else printf("/dev/mem read buf = %ld\n", *(unsigned long *)buf); } close(fd); return n; } int main(int argc, char **argv) { FILE *fp; char addr_str[11]="0x"; char var[51]; unsigned long addr; unsigned long jiffies; char ch; int r; if (argc != 2) { fprintf(stderr,"usage: %s System.map\n",argv[0]); exit(-1); } if ((fp = fopen(argv[1],"r")) == NULL) { perror("fopen"); exit(-1); } do { r = fscanf(fp,"%8s %c %50s\n",&addr_str[2],&ch,var); // format of System.map if (strcmp(var,"jiffies")==0) break; } while(r > 0); if (r < 0) { printf("could not find jiffies\n"); exit(-1); } addr = strtoul(addr_str,NULL,16); //Convert string to unsigned long integer printf("found jiffies at (%s) %08lx\n",addr_str,addr); read_kmem(addr, &jiffies, sizeof(jiffies)); printf("jiffies=%ld (read from virtual memory)\n\n", jiffies); jiffies = 0; //reinit for checking read_mem() below read_mem(addr-0xC0000000, &jiffies, sizeof(jiffies)); printf("jiffies=%ld (read from physical memory)\n", jiffies); return 0; } 

对于情况1中的无效参数,问题被偏移为非页面对齐。 mmap(2)通过操作页面表来工作,而且这种工作只能在页面大小乘以大小和偏移量的情况下工作

至于第二种情况,我不确定你是否保证有内核空间从3G边界开始。 另外,我敢肯定,这是内核虚拟空间的边界,而不是物理内存中的位置 – 所以在beagle板上,很可能你会得到一个指向谁知道的地方。

我认为你可能需要的是PHYS_OFFSET而不是 PAGE_OFFSET

我已经尝试过组合或抵消和bs为dd,并发现这个解决方案:

在PC上,在建立目录中,我找到了jiffies的位置。

grep -w jiffies System.map
jiffies

在PandaBoard上:

在/ proc / iomem中你可以看到:

80000000-9c7fffff:系统RAM
80008000-80435263:内核代码
80464000-804d0d97:内核数据
a0000000-bfefffff:系统RAM

RAM从物理80000000开始,内核数据从80464000开始。看起来类似于jiffies的地址。

然后从虚拟地址转换为phys:virt – 0xC000000 + 0x8000000。

dd if = / dev / mem skip = $((0x804660c))bs = $((0x10))count = 1 2> / dev / null | hexdump都
0000000 02b9 0002 0001 0000 0000 0000 0000 0000
0000010

尝试几次,看看价值是如何增加。

总结:/ dev / mem使用phys地址,RAM从phys地址0x8000000开始