11

私の投稿を更新しました...

私はプログラムの下に着きました。とで動作し/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:無効な引数」はなぜですか?(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;
} 
4

2 に答える 2

4

ddの組み合わせまたはoffsetとbsを試しましたが、次の解決策が見つかりました。

PCのビルドディレクトリで、jiffiesの場所を見つけました。

grep -w jiffies System.map
c04660c0 D 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から始まります

于 2012-11-10T18:11:33.617 に答える
2

ケース1の無効な引数の場合、問題はオフセットがページ整列されていないことです。mmap(2)は、ページテーブルを操作することによって機能します。このような機能は、サイズとオフセットの両方のページサイズの倍数でのみ機能します。

2番目のケースについては、カーネルスペースが3G境界で始まることが保証されているかどうかはわかりません。また、これはカーネルの仮想空間の境界であり、物理メモリ内の場所ではないと確信しています。ビーグルボードでは、誰がどこを知っているかを示すラップアラウンドオフセットになってしまう可能性があります。

必要なのは、 PAGE_OFFSETではなく PHYS_OFFSETだと思います。

于 2012-07-13T01:28:49.643 に答える