【问题标题】:write on /dev/mem fails with bad address在 /dev/mem 上写入失败,地址错误
【发布时间】:2020-03-20 10:41:24
【问题描述】:

我正在尝试从用户空间访问 /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;
}

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

【问题讨论】:

  • 您对问题的更改使我的回答难以理解。请不要在给出答案/评论后更改问题,而仅添加内容。
  • @md.jamal:实际代码(如果函数失败仅调用perror)是否显示lseek: Success?如果是这样lseek 失败。
  • Lseek 成功写入失败 我已经更新了代码和输出
  • @md.jamal 看看mmap(),UART 寄存器不在进程虚拟地址空间
  • 或许你可以用strace看看devmem是如何读/写内存的……

标签: c linux io arm qemu


【解决方案1】:

尝试使用 /dev/mem 上的 read 和 write 系统调用来访问设备寄存器并不是一个好主意。 /dev/mem 实现这些系统调用主要是为了方便访问 RAM,如果您尝试在带有设备的地址空间区域上执行此操作,则无法保证它是否会为设备进行正确宽度的访问。对于访问设备,您应该使用 mmap() 然后直接访问正确的地址(这使您可以更好地控制访问的宽度以及确切地触摸了哪些地址)。例如,您可以查看 devmem 本身的源代码:https://github.com/hackndev/tools/blob/master/devmem2.c -- 不到 100 行代码,它非常简单,您已经知道它适用于您的用例。

【讨论】:

    【解决方案2】:

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

    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() 的调用也是如此,顺便说一句。

    【讨论】:

      猜你喜欢
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多