【问题标题】:How do I read data from bar 0, from userspace, on a pci-e card in linux?如何在 linux 的 pci-e 卡上从用户空间的 bar 0 读取数据?
【发布时间】:2014-09-22 17:24:39
【问题描述】:

在 Windows 上有一个名为 pcitree 的程序,它允许您在不编写设备驱动程序的情况下设置和读取内存。是否有 pcitree 的 linux 替代品可以让我读取我的 pcie 卡块 0 上的内存?

一个简单的用例是我使用驱动程序代码在我的 pci-e 卡的第 0 块的第一个内存地址上写入一个 32 位整数。然后我使用 pcitree 替代方法读取块零的第一个内存地址的值并查看我的整数。

谢谢

【问题讨论】:

    标签: linux driver pci


    【解决方案1】:

    我在网上找到了一些代码,可以在这里github.com/billfarrow/pcimem 做我想做的事情。 据我了解,此链接提供了通过系统调用“mmap”将内核内存映射到用户内存的代码

    这主要是从程序的自述文件和 mmap 的手册页中窃取的。 mmap 需要

    • 起始地址
    • 尺寸
    • 内存保护标志
    • 链接到您的 pci 卡的 bar0 的文件描述符。
    • 和偏移量

    mmap 返回一个用户空间指针,指向由起始地址和大小参数定义的内存。

    此代码显示了 mmap 用法的示例。

    //The file handle can be found by typing "lspci -v "
    //    and looking for your device.
    fd = open("/sys/devices/pci0001\:00/0001\:00\:07.0/resource0", O_RDWR | O_SYNC);
    //mmap returns a userspace address
    //0, 4096 tells it to pull one page 
    ptr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    printf("PCI BAR0 0x0000 = 0x%4x\n", *((unsigned short *) ptr);
    

    【讨论】:

    • 我会在两天后接受这个答案。很抱歉浪费了您的时间。
    • 尤其是像 github 这样的网站。
    • 由于一些新的内核锁定 (man kernel_lockdown.7) 这不再有效。有人知道另一种方法吗?
    【解决方案2】:

    我使用上面描述的获取 PCI BAR0 寄存器的方法,但是得到了分段错误。我使用 gdb 从我的代码中调试错误,如下所示,它显示 mmap() 的返回值为 (void *) 0xffffffffffffffff

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <ctype.h>
    #include <termios.h>
    #include <sys/types.h>
    #include <sys/mman.h>
    
    #define PRINT_ERROR \
            do { \
                    fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
                    __LINE__, __FILE__, errno, strerror(errno)); exit(1); \
            } while(0)
    
    #define MAP_SIZE 4096UL
    #define MAP_MASK (MAP_SIZE - 1)
    
    int main(int argc, char **argv) {
    
        int fd;
        void *ptr;
        //The file handle can be found by typing lscpi -v
        //and looking for your device.
        fd = open("/sys/bus/pci/devices/0000\:00\:05.0/resource0", O_RDWR | O_SYNC);
        //mmap returns a userspace address
        //0, 4096 tells it to pull one page
        ptr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        printf("PCI BAR0 0x0000 = 0x%4x\n", *((unsigned short *) ptr));
    
        if(munmap(ptr, 4096) == -1) PRINT_ERROR;
        close(fd);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      在内核中运行 /dev/mem 的系统上,可以使用以下命令读取设备的条形图:

      sudo dd if=/dev/mem skip=13701120 count=1 bs=256 | hexdump
      

      查看 dd 手册页。在上面的示例中,13701120 * 256 是读取 256 字节的起始物理地址。

      【讨论】:

        猜你喜欢
        • 2013-10-02
        • 1970-01-01
        • 2015-02-24
        • 2012-10-10
        • 1970-01-01
        • 2017-03-16
        • 1970-01-01
        • 2012-10-09
        • 1970-01-01
        相关资源
        最近更新 更多