5

请告诉我,为什么我的简单应用程序无法映射小内存?

而且,为什么会有这样一个特定的边界 - 257UL?

// #define MAP_SIZE 256UL or below - fail
// #define MAP_SIZE 257UL - ok

#include <stdio.h>
#include <stdlib.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 FATAL 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 *map_base, *virt_addr;
    unsigned long read_result, writeval;
    off_t target = strtoul("0x00002000", 0, 0);

    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    printf("/dev/mem opened.\n");
    fflush(stdout);

    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
    if(map_base == (void *) -1) FATAL;
    printf("Memory mapped at address %p.\n", map_base);
    fflush(stdout);
...
}
4

2 回答 2

4

可能你只是没有写信的权利/dev/mem。这可能不是您想要的,将所有低端物理内存映射到您的地址空间。

查看shm_open打开内存段或MAP_ANONYMOUS匿名映射。

编辑:

做一个man mem来知道/dev/mem设备节点是关于什么的:

mem 中的字节地址被解释为物理内存地址。对不存在的位置的引用会导致返回错误。

如果您想映射到设备节点以拥有您应该使用的内存段/dev/zero,但现在我上面描述的工具应该足够了。

然后不要,真的不要,用 root 权限运行这样的代码,除非你真的知道你在做什么。写入物理内存并因此覆盖内核和用户空间数据和程序只会导致灾难。

于 2012-10-10T09:08:43.550 回答
3

mmap 在您的系统上以页面大小的倍数工作。如果您在 i386/amd64 或实际上是最现代的 CPU 上执行此操作,则为 4096。

在我系统上的 mmap 手册页中,它说:“偏移量必须是 sysconf(_SC_PAGE_SIZE) 返回的页面大小的倍数。”。在某些系统上,由于历史原因,长度参数可能不是页面大小的倍数,但在这种情况下 mmap 无论如何都会四舍五入到整页。

于 2012-10-10T09:45:23.200 回答