2013-08-24 20 views
18

Dostaję -EINVAL z jakiegoś powodu i nie jest dla mnie jasne, dlaczego. Oto gdzie mogę otworzyć i próba mmap plik:Niepoprawny argument dla odczytu i zapisu mmap?

if ((fd = open(argv[1], O_RDWR)) < 0) 
{ 
    fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); 
    return 1; 
} 

struct stat statbuf; 
if (fstat(fd, &statbuf)) 
{ 
    fprintf(stderr, "stat filed: %s\n", strerror(errno)); 
    return 1; 
} 

char* fbase = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
if (fbase == MAP_FAILED) 
{ 
    fprintf(stderr, "mmap failed: %s\n", strerror(errno)); 
    return 1; 
} 

EDIT: dodam, błąd występuje w mmap.

+0

Co masz na myśli? To jest fragment z czegoś, co piszę. – Alex

+0

Pytanie brzmi "gdzie", w którym wierszu kodu fragment EINVAL występują. – alk

+0

Przepraszam, zapomniałem określić. Błąd jest w mmap. – Alex

Odpowiedz

49

Okazuje się, zmieniając MAP_SHARED do MAP_PRIVATE pozwala na to, aby odnieść sukces.

Powód tego niepowodzenia był subtelny: mój kod działa w maszynie wirtualnej VirtualBox, a plik, który próbowałem przetestować pod numerem mmap, znajdował się we współużytkowanym katalogu na komputerze hosta. Wirtualny system plików VirtualBox najwyraźniej nie implementuje mmap z opcją MAP_SHARED przez granicę hiperwizora.

Jeśli przeczytasz pomocne komentarze jxh zarówno na moje pytanie, jak i na jego odpowiedź, okazuje się, że ten kod był dla niego skuteczny, ponieważ prawdopodobnie próbował pobrać do pamięci hosta plik systemu hosta (mmap).

Moja obserwacja, że ​​przełączanie z MAP_SHARED na MAP_PRIVATE jest również zgodne z tym: ponieważ prywatnie mapowana pamięć jest niewidoczna dla innych procesów, sterownik wirtualnego systemu plików prawdopodobnie nie będzie miał zastrzeżeń do mapowania pamięci.

Rozwiązaniem było przeniesienie pliku, który chciałem odwzorować na dysk twardy gościa i wykonanie tam manipulacji.

+2

To dobre znalezisko, +1. – jxh

+2

To rozwiązało to dla mnie! – arnoapp

+2

To dlatego kocham stackoverflow. – Claudiu

13

Twoja statbuf.st_size to 0. mmap() zakończy się niepowodzeniem, jeśli parametr o długości ma wartość 0.

Istnieją 3 wymienione powody EINVAL błędu mmap():

void *mmap(void *addr, size_t length, int prot, int flags, 
      int fd, off_t offset); 

...

  • Nie lubimy addr, length lub offset (na przykład są zbyt duże lub nie wyrównane na granicy strony).
  • (od wersji Linuksa 2.6.12) length było 0.
  • flags zawierał ani MAP_PRIVATE lub MAP_SHARED lub zawierały obu tych wartości.
+0

Czuję się jak kretyn, ale: było zero, zastąpiłem pusty plik i okazało się, że problem się utrzymuje. – Alex

+0

Chociaż długość była zerowa poprzednio, upewniłem się, że plik jest niepusty, a problem nadal występuje. To pytanie jest bałaganem, otworzę nowy z większą ilością szczegółów. – Alex

+0

Skompilowałem i uruchomiłem twój kod na moim systemie Linux. – jxh