Pourquoi remap_file_pages () échoue-t-il dans cet exemple?
-
19-09-2019 - |
Question
Le code C suivant illustre un problème que je vois sur Linux 2.6.30.5-43.fc11.x86_64:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[1024];
void *base;
int fd;
size_t pagesz = sysconf(_SC_PAGE_SIZE);
fd = open("<some file, at least 4*pagesz in length>", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
base = mmap(0, 4*pagesz, PROT_READ, MAP_SHARED, fd, 0);
if (base < 0) {
perror("mmap");
close(fd);
return 1;
}
memcpy(buf, (char*)base + 2*pagesz, 1024);
if (remap_file_pages(base, pagesz, 0, 2, 0) < 0) {
perror("remap_file_pages");
munmap(base, 4*pagesz);
close(fd);
return 1;
}
printf("%d\n", memcmp(buf, base, 1024));
munmap(base, 4*pagesz);
close(fd);
return 0;
}
Cela échoue toujours avec remap_file_pages () renvoyant -1 et errno set sur einval. En regardant la source du noyau, je peux voir toutes les conditions dans remap_file_pages () où elle pourrait échouer, mais aucune ne semble s'appliquer à mon exemple. Que se passe-t-il?
La solution
Il est causé par l'ouverture du fichier O_RDONLY
. Si vous changez le mode ouvert pour O_RDWR
, ça marche (même si le mmap()
Spécifie toujours juste PROT_READ
).
Ce code dans do_mmap_pgoff
est la cause profonde - elle ne marque que le VMA VM_SHARED
Si le fichier a été ouvert pour écrire:
vm_flags |= VM_SHARED | VM_MAYSHARE;
if (!(file->f_mode & FMODE_WRITE))
vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
Alors dans remap_file_pages()
, vous échouez sur le premier chèque:
if (!vma || !(vma->vm_flags & VM_SHARED))
goto out;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow