Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何使用/dev/kmem?_C_Linux_Mmap - Fatal编程技术网

C 如何使用/dev/kmem?

C 如何使用/dev/kmem?,c,linux,mmap,C,Linux,Mmap,更新我的帖子 我在程序下面。它在/dev/kmem和/dev/mem上运行 我想我可以从代码中学到一些东西。但当我在我的小猎犬板上运行它时,给出了以下结果: 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 jiffi

更新我的帖子

我在程序下面。它在
/dev/kmem
/dev/mem
上运行

我想我可以从代码中学到一些东西。但当我在我的小猎犬板上运行它时,给出了以下结果:

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\u kmem()
工作正常,但是
read\u mem()
不工作,而且传输到它的“偏移量”似乎是错误的。但是内核地址-
页偏移量(0xC0000000)=物理地址-
,它错了吗

我的问题是: (1) 为什么在案例1中使用“mmap:Invalid argument”? (2) 为什么mmap只映射
页面大小
长度空间? (3) 读取内存有什么问题

有人能帮忙吗? 谢谢

/*
*getjiff.c
*
*此工具包展示了如何从用户空间获取jiffies值:
* 1. 从内核映像中查找jiffies的地址。
* 2. 访问虚拟地址空间以获取jiffies值。
* 3. 访问物理地址sapce以获取jiffies值。
*
*演示以下技巧:
*o通过调用nlist()获取ELF对象符号地址
*o从/dev/kmem访问虚拟内存空间
*o从/dev/mem访问虚拟内存空间
*/
#包括
#包括//退出
#包括//n列表
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义长*(易失性无符号长*)
/*从虚拟内存读取*/
int read_kmem(偏移量、空*小单位、大小计数)
{
int-fd;
int n;
fd=打开(“/dev/kmem”,仅适用于);
如果(fd<0)
{
perror(“open/dev/kmem失败”);
返回-1;
}
lseek(fd、偏移、寻道集);
n=读取(fd、buf、计数);
如果(n!=计数)
perror(“/dev/kmem读取失败”);
其他的
printf(“/dev/kmem read buf=%ld\n”,*(无符号长*)buf);
关闭(fd);
返回n;
}
/*从物理内存读取*/
int read_mem(偏移量、空*小单位、大小计数)
{
int-fd;
int n;
整版大小;
void*地图库;
无符号长值;
printf(“/dev/mem:offset是%lx\n”,offset);
fd=打开(“/dev/mem”,仅限ordu);
如果(fd<0)
{
perror(“open/dev/mem失败”);
返回-1;
}
如果(1){
页面大小=getpagesize();
printf(“页面大小=%d\n”,页面大小);
map\u base=mmap(0,页面大小,PROT\u读取,map\u共享,fd,偏移);
if(map\u base==map\u失败){
佩罗尔(“mmap”);
出口(1);
}
值=长(地图\基础);
printf(“/dev/mem:value是%ld\n”,value);
buf=(无符号长*)映射_基;
}
如果(0){
lseek(fd、偏移、寻道集);
n=读取(fd、buf、计数);
如果(n!=计数)
perror(“/dev/mem读取失败”);
其他的
printf(“/dev/mem read buf=%ld\n”,*(无符号长*)buf);
}
关闭(fd);
返回n;
}
int main(int argc,字符**argv)
{
文件*fp;
char addr_str[11]=“0x”;
char-var[51];
无符号长地址;
未签名的长jiffies;
char ch;
INTR;
如果(argc!=2){
fprintf(stderr,“用法:%s System.map\n”,argv[0]);
出口(-1);
}
if((fp=fopen(argv[1],“r”)==NULL){
佩罗尔(“福彭”);
出口(-1);
}
做{
r=fscanf(fp,“%8s%c%50s\n”,&addr_str[2],&ch,var);//System.map的格式
if(strcmp(var,“jiffies”)==0)
打破
}而(r>0);
if(r<0){
printf(“找不到jiffies\n”);
出口(-1);
}
addr=strtoul(addr_str,NULL,16);//将字符串转换为无符号长整数
printf(“在(%s)%08lx\n”地址找到了jiffies,addr\u str,addr);
read_kmem(地址和地址),sizeof(地址和地址);
printf(“jiffies=%ld(从虚拟内存读取)\n\n”,jiffies);
jiffies=0;//重新输入以检查下面的read\u mem()
read_mem(addr-0xC0000000和jiffies,sizeof(jiffies));
printf(“jiffies=%ld(从物理内存读取)\n”,jiffies);
返回0;
} 

对于案例1中的无效参数,问题是偏移量未对齐页面mmap(2)通过操纵页面表来工作,并且这种工作方式仅适用于大小和偏移量的页面大小的倍数

至于第二种情况,我不确定是否保证内核空间从3G边界开始。另外,我很确定这是内核的虚拟空间的边界,而不是物理内存中的位置-所以在beagle board上,很可能你最终得到了一个缠绕的偏移点,谁知道它在哪里


我想您可能需要的是,不是页偏移量

我尝试了dd的组合或偏移量和bs,并找到了此解决方案:

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

grep-w jiffies System.map
c04660c0 D jiffies

在船上:

在/proc/iomem中,您可以看到:

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

RAM从物理8000000开始,内核数据从80464000开始。看起来和jiffies的地址相似

然后将虚拟地址转换为phys:virt-0xC000000+0x8000000

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

尝试几次,看看值是如何递增的

概要:/dev/mem使用物理地址,RAM从物理地址0x8000000开始
什么是
/proc/sys/vm/mmap\u min\u addr
?如果它不是0,那么内核将拒绝对空页的mmap。每当发现空指针异常错误时,对空地址执行mmap通常是利用linux内核的一种流行方式。感谢您的回复!mmap_min_addr的值为32768。我可以将其更改为0。但还是我的
/*
* 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;
}