为什么mmap / dev / mem返回不同的地址?

时间:2023-01-18 17:51:09

Here is the program:

这是程序:

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/file.h>
#include <errno.h>

long* mapmem(off_t offset)
{
    int fd;
    long *ret;

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

    if (fd == -1) {
        perror("open");
        return NULL;
    }

    printf("offset (pageaddr) is: %ld\n", offset);

    ret = mmap(0, sizeof(long), PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
    if (ret == MAP_FAILED) {
        perror("mmap");
        ret = NULL;
    }

    printf("Return address is: %p\n", ret);

    if (close(fd) == -1)
        perror("close");

    return ret;
}

int main(int argc, char *argv[])
{
    long *mem = 0;
    volatile long *_mem = 0, dummy;
    long long int addr, offset, pageaddr;
    char *endpt;

    if (argc != 2) {
        fprintf(stderr, "Usage %s <addr>\n", argv[0]);
        return 1;
    }

    addr = strtoll(argv[1], &endpt, 16);
    offset = addr % sysconf(_SC_PAGE_SIZE);
    pageaddr = addr - offset;

    printf("addr is: %lld, offset: %lld, pageaddr: %lld\n", addr, offset, pageaddr);

    mem = mapmem(pageaddr);

    return 0;
}

Why is the mmaped physical address different fro what we passed into? Or is the address returned virtual address that mapped to the corresponding physical address?

为什么mmaped物理地址与我们传入的物理地址不同?或者是地址返回映射到相应物理地址的虚拟地址?

My output for running the above program:

我运行上述程序的输出:

 $ sudo ./test 0x12345
addr is: 74565, offset: 837, pageaddr: 73728
offset is: 73728
Return address is: 0x7f3081fc0000

1 个解决方案

#1


1  

Mmap returns an address of a memory buffer you can access: as such, it is a virtual address, also because physical addresses are supposed not be visible to userspace. Indeed, current architectures always (but in the very early seconds of the boot process) run with memory virtualization enabled. You see physical addresses only inside the kernel, and only if you work with physical memory explicitly; but you never can access them directly, you first need to map them to virtual addresses.

Mmap返回您可以访问的内存缓冲区的地址:因此,它是一个虚拟地址,也是因为用户空间不应该看到物理地址。实际上,当前的体系结构总是(但在引导过程的最初几秒)在启用内存虚拟化的情况下运行。您只在内核中看到物理地址,并且只有在您明确使用物理内存时才会看到;但是你永远无法直接访问它们,首先需要将它们映射到虚拟地址。

What you see in your program is thus a virtual address, which differs from time to time. When you mmap, Linux chooses a free virtual memory area inside your process' virtual memory that is big enough to accomodate the mapping you are requesting, and maps the physical memory to that area. Which virtual memory area Linux selects depends on the availability and on other factors like Address space layout randomization (http://en.wikipedia.org/wiki/Address_space_layout_randomization).

因此,您在程序中看到的是一个虚拟地址,它不时会有所不同。当您使用mmap时,Linux会在进程的虚拟内存中选择一个空闲的虚拟内存区域,该区域足以容纳您请求的映射,并将物理内存映射到该区域。 Linux选择哪个虚拟内存区域取决于可用性以及地址空间布局随机化等其他因素(http://en.wikipedia.org/wiki/Address_space_layout_randomization)。

#1


1  

Mmap returns an address of a memory buffer you can access: as such, it is a virtual address, also because physical addresses are supposed not be visible to userspace. Indeed, current architectures always (but in the very early seconds of the boot process) run with memory virtualization enabled. You see physical addresses only inside the kernel, and only if you work with physical memory explicitly; but you never can access them directly, you first need to map them to virtual addresses.

Mmap返回您可以访问的内存缓冲区的地址:因此,它是一个虚拟地址,也是因为用户空间不应该看到物理地址。实际上,当前的体系结构总是(但在引导过程的最初几秒)在启用内存虚拟化的情况下运行。您只在内核中看到物理地址,并且只有在您明确使用物理内存时才会看到;但是你永远无法直接访问它们,首先需要将它们映射到虚拟地址。

What you see in your program is thus a virtual address, which differs from time to time. When you mmap, Linux chooses a free virtual memory area inside your process' virtual memory that is big enough to accomodate the mapping you are requesting, and maps the physical memory to that area. Which virtual memory area Linux selects depends on the availability and on other factors like Address space layout randomization (http://en.wikipedia.org/wiki/Address_space_layout_randomization).

因此,您在程序中看到的是一个虚拟地址,它不时会有所不同。当您使用mmap时,Linux会在进程的虚拟内存中选择一个空闲的虚拟内存区域,该区域足以容纳您请求的映射,并将物理内存映射到该区域。 Linux选择哪个虚拟内存区域取决于可用性以及地址空间布局随机化等其他因素(http://en.wikipedia.org/wiki/Address_space_layout_randomization)。