在 /dev/mem 上写入失败,地址错误

write on /dev/mem fails with bad address

我正在尝试从用户 space 访问 /dev/mem。为此目的使用 qemu-system-arm。

UART0 已映射:0x101f1000 并且 UARTDR 位于偏移量 0x0

$ devmem 0x101f1000 8 0x61

上面在控制台上写'a'。

当我尝试从 C 代码实现相同的逻辑时,它失败了

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(int argc, char *argv[])
{

    int fd;
    char ch = 'a';

    fd = open("/dev/mem", O_RDWR | O_SYNC);

    if (fd < 0) {
        perror("open failed");
        return -1;
    }

    if (lseek(fd, 0x101f1000, SEEK_SET) == -1) {
        perror("lseek");    
    }

    if (write(fd, &ch, sizeof(ch)) == -1) {
        perror("write");
    }

    close(fd);

    return 0;
}

失败并出现错误: 写:地址错误

[可能不是你的主要问题,但仍然]

lseek: Success
write: Bad address

您只想使用 errno(或调用 perror())是之前的调用失败(记录为失败时设置 errno)。

所以这个

lseek(fd, 0x101f1000, SEEK_SET);
perror("lseek");

应该看起来像

if ((off_t) -1 == lseek(fd, 0x101f1000, SEEK_SET))
{
  perror("lseek() failed");
}

write() 的调用也是如此,顺便说一句。

尝试使用 /dev/mem 上的读写系统调用来访问设备寄存器不是一个好主意。 /dev/mem 实现这些系统调用主要是为了方便访问 RAM,如果您尝试在地址区域 space那里有一个设备。对于访问设备,您应该改用 mmap(),然后直接访问正确的地址(这使您可以更好地控制访问宽度以及确切地访问哪些地址)。例如,您可以查看 devmem 本身的源代码:https://github.com/hackndev/tools/blob/master/devmem2.c - 不到 100 行代码,它非常简单,您已经知道它适用于您的用例。