21

我得到-EINVAL了某种原因,我不清楚为什么。这是我打开并尝试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;
}

编辑:我应该补充一点,错误发生在mmap.

4

2 回答 2

58

Turns out changing the MAP_SHARED to MAP_PRIVATE allows this to succeed.

This reason this was failing is subtle: My code is running inside a VirtualBox VM, and the file I was attempting to mmap was in a shared directory on my host machine. The VirtualBox virtual filesystem apparently doesn't implement mmap with the MAP_SHARED option across the boundary of the hypervisor.

If you'll read jxh's helpful comments on both my question and on his answer, it turns out that this code was working for him because he was likely attempting to mmap a host filesystem file into the host memory.

My observation that switching from MAP_SHARED to MAP_PRIVATE is also consistent with this: since privately mapped memory is invisible to other processes, the virtual filesystem driver will probably have no objection to mapping the memory.

The solution was to move the file I wanted to map into the guest's hard drive and perform manipulation from there.

于 2013-08-24T17:10:19.387 回答
16

statbuf.st_size的是0mmap()如果长度参数为0.

列出了 3 个EINVAL错误原因mmap()

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

...

  • 我们不喜欢addr, length, or offset(例如,它们太大,或者没有在页面边界上对齐)。
  • (自 Linux 2.6.12 起)length为 0。
  • flags不包含MAP_PRIVATEMAP_SHARED,或包含这两个值。
于 2013-08-24T16:13:14.210 回答