【发布时间】:2014-09-22 17:24:39
【问题描述】:
在 Windows 上有一个名为 pcitree 的程序,它允许您在不编写设备驱动程序的情况下设置和读取内存。是否有 pcitree 的 linux 替代品可以让我读取我的 pcie 卡块 0 上的内存?
一个简单的用例是我使用驱动程序代码在我的 pci-e 卡的第 0 块的第一个内存地址上写入一个 32 位整数。然后我使用 pcitree 替代方法读取块零的第一个内存地址的值并查看我的整数。
谢谢
【问题讨论】:
在 Windows 上有一个名为 pcitree 的程序,它允许您在不编写设备驱动程序的情况下设置和读取内存。是否有 pcitree 的 linux 替代品可以让我读取我的 pcie 卡块 0 上的内存?
一个简单的用例是我使用驱动程序代码在我的 pci-e 卡的第 0 块的第一个内存地址上写入一个 32 位整数。然后我使用 pcitree 替代方法读取块零的第一个内存地址的值并查看我的整数。
谢谢
【问题讨论】:
我在网上找到了一些代码,可以在这里github.com/billfarrow/pcimem 做我想做的事情。 据我了解,此链接提供了通过系统调用“mmap”将内核内存映射到用户内存的代码
这主要是从程序的自述文件和 mmap 的手册页中窃取的。 mmap 需要
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);
【讨论】:
我使用上面描述的获取 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;
}
【讨论】:
在内核中运行 /dev/mem 的系统上,可以使用以下命令读取设备的条形图:
sudo dd if=/dev/mem skip=13701120 count=1 bs=256 | hexdump
查看 dd 手册页。在上面的示例中,13701120 * 256 是读取 256 字节的起始物理地址。
【讨论】: