2014-02-18 5 views
0

Вот программа:Почему mmap/dev/mem возвращает другой адрес?

#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; 
} 

Почему mmaped физический адрес отличается сюда то, что мы прошли в? Или адрес вернул виртуальный адрес, сопоставленный с соответствующим физическим адресом?

Мой выход для запуска выше программы:

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

'man mem: mem - это файл символьного устройства, представляющий собой изображение основной памяти компьютера.« Я предполагаю, что это означает, что ваша программа запрашивает ОС для отображения физического адреса основной памяти на какой-либо адрес в виртуальном пространство вашего процесса. –

+0

Почему вы считаете, что виртуальные адреса должны совпадать с физическими адресами? –

+0

@BasileStarynkevitch Я просто хочу подтвердить, что возвращенный адрес находится в виртуальном адресном пространстве моей текущей запущенной программы, даже если отображение из '/ dev/mem'. Я думаю, что это так. Для обычного адреса я знаю, что он находится в виртуальном адресном пространстве. – Amumu

ответ

1

ММАП возвращает адрес буфера памяти можно получить доступ: как таковой, это виртуальный адрес, а также потому, что физические адреса должны не быть видны в пользовательском пространстве. Действительно, текущие архитектуры всегда (но в самые первые секунды процесса загрузки) запускаются с включенной виртуализацией памяти. Вы видите физические адреса только внутри ядра и только если вы явно работаете с физической памятью; но вы никогда не можете получить к ним доступ напрямую, сначала вам нужно сопоставить их с виртуальными адресами.

Таким образом, вы видите в своей программе виртуальный адрес, который время от времени отличается. Когда вы mmap, Linux выбирает свободную область виртуальной памяти внутри виртуальной памяти вашего процесса, которая достаточно велика, чтобы разместить сопоставление, которое вы запрашиваете, и отображает физическую память в эту область. Какая область виртуальной памяти, выбранная Linux, зависит от доступности и от других факторов, таких как рандомизация размещения адресного пространства (http://en.wikipedia.org/wiki/Address_space_layout_randomization).

Смежные вопросы