【问题标题】:Invalid argument for read-write mmap?读写 mmap 的参数无效?
【发布时间】:2013-08-24 16:05:17
【问题描述】:

出于某种原因,我收到了-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 中发生了错误。

【问题讨论】:

  • 什么意思?这是我正在写的东西的 sn-p。
  • 问题是在代码的哪一行 sn-p EINVAL 发生在“哪里”。
  • 对不起,我忘了指定。错误在 mmap 中。
  • st_size的值是多少?

标签: c linux virtualbox mmap


【解决方案1】:

原来将MAP_SHARED 更改为MAP_PRIVATE 可以成功。

这个失败的原因很微妙:我的代码在 VirtualBox VM 中运行,而我试图 mmap 的文件位于我主机上的共享目录中。 VirtualBox 虚拟文件系统显然没有在管理程序的边界上使用MAP_SHARED 选项实现mmap

如果您阅读 jxh 对我的问题和他的回答很有帮助的 cmets,就会发现这段代码对他有用,因为他可能试图将主机文件系统文件 mmap 到主机内存中。

我观察到从MAP_SHARED切换到MAP_PRIVATE也与此一致:由于私有映射的内存对其他进程是不可见的,因此虚拟文件系统驱动程序可能不会反对映射内存。

解决方案是将我想要映射的文件移动到客人的硬盘驱动器并从那里执行操作。

【讨论】:

  • 这就是我喜欢stackoverflow的原因。
  • 请不要认为从MAP_SHARED 切换到MAP_PRIVATE 是一个实际的解决方案。这甚至不是解决方法。使用MAP_SHARED 就地修改输出文件的程序将在使用MAP_PRIVATE 时静默失败。它可能看起来有效,但可能不是。
【解决方案2】:

您的statbuf.st_size0。如果 length 参数为 0mmap() 将失败。

EINVAL 错误mmap() 列出的原因有 3 个:

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

...

  • 我们不喜欢 addrlengthoffset(例如,它们太大,或未在页面边界上对齐)。
  • (自 Linux 2.6.12 起)length 为 0。
  • flags 既不包含 MAP_PRIVATEMAP_SHARED,或者包含这两个值。

【讨论】:

  • 我觉得自己像个白痴,但是:它是零,我已经替换了空文件,结果问题仍然存在。
  • 虽然之前的长度为零,但我确保文件不是空的,并且问题仍然存在。这个问题一团糟,我再开一个更详细的问题。
  • 我一定是疯了。我在一个干净的文件中尝试了它并且它有效,然后我尝试将完全相同的代码粘贴到它失败的文件中。
  • 事实证明,设置MAP_PRIVATE 而不是MAP_SHARED 就足以让它工作。
  • 这并不能解释什么,因为你说代码就像在一个干净的文件中一样工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 1970-01-01
相关资源
最近更新 更多