简体   繁体   English

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

[英]write on /dev/mem fails with bad address

I am trying accessing /dev/mem from user space.我正在尝试从用户空间访问 /dev/mem。 Using qemu-system-arm for this purpose.为此目的使用 qemu-system-arm。

UART0 is mapped: 0x101f1000 and UARTDR is placed at offset 0x0 UART0 被映射:0x101f1000 和 UARTDR 被放置在偏移量 0x0

$ devmem 0x101f1000 8 0x61

The above writes 'a' on the console.以上在控制台上写了'a'。

When i try the achieve the same logic from C code, it fails当我尝试从 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;
}

It fails with error: write: Bad address它失败并出现错误:写:地址错误

Trying to access device registers by using the read and write syscalls on /dev/mem is not a good idea.尝试通过使用 /dev/mem 上的读写系统调用来访问设备寄存器不是一个好主意。 /dev/mem implements those syscalls mostly for convenience in accessing RAM, and there is no guarantee about whether it will make accesses of the right width for the device if you try to do that on an area of the address space with a device there. /dev/mem 实现这些系统调用主要是为了方便访问 RAM,如果您尝试在具有设备的地址空间区域上执行此操作,则无法保证它是否会为设备访问正确的宽度。 For accessing devices you should instead use mmap() and then access the right addresses directly (which gives you more control about the width of the access and exactly which addresses are touched).对于访问设备,您应该改用 mmap(),然后直接访问正确的地址(这使您可以更好地控制访问的宽度以及确切地触摸哪些地址)。 For an example of this you can look at the source code for devmem itself: https://github.com/hackndev/tools/blob/master/devmem2.c -- at less than 100 lines of code it's very simple and you already know it works correctly for your use case.举个例子,你可以查看 devmem 本身的源代码: https : //github.com/hackndev/tools/blob/master/devmem2.c——不到 100 行代码,它非常简单,你已经知道它适用于您的用例。

[probably not your main problem but still] [可能不是你的主要问题,但仍然]

 lseek: Success write: Bad address

You only want to use errno (or call perror() ) is the previous call failed (and is documented to set errno on failure).您只想使用errno (或调用perror() )是前一次调用失败(并且记录为在失败时设置errno )。

So this所以这

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

should look like应该看起来像

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

Same for the call to write() , BTW.write()的调用也是如此,顺便说一句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM