【发布时间】:2016-11-22 22:43:50
【问题描述】:
mmap64()的函数调用如下:
addr = (unsigned char*) mmap64(NULL, regionSize, PROT_READ|PROT_WRITE, MAP_SHARED, FileDesc, (unsigned long long)regionAddr);
参数通常具有如下值:
regionSize = 0x20000;
FileDesc = 27;
regionAddr = 0x332C0000;
显然,这些值在代码中并没有像那样硬编码,但我只想向您展示它们的典型值。
问题:
mmap64() 调用在 Red Hat Linux 6.6 中完美运行,内核版本:2.6.32-504.16.2.el6.x86_64。在 Red Hat Linux 7.2 中失败,内核版本:3.10.0-327.13.1.el7.x86_64。
据我所知,代码没有区别。
返回的 errno 是“无效参数”或 errno #22 (EINVAL)。查看此参考资料http://linux.die.net/man/3/mmap64,我发现 EINVAL 错误有 3 种可能性:
- 我们不喜欢 addr、length 或 offset(例如,它们太大,或未在页面边界上对齐)。 -> 在我的情况下很可能是罪魁祸首。
- (从 Linux 2.6.12 开始)长度为 0。 -> 不可能,我在调试打印中检查了长度(regionSize)值,它是 0x20000。
- 标志既不包含 MAP_PRIVATE 也不包含 MAP_SHARED,或者同时包含这两个值。 -> 从我的函数调用中可以看出,不可能是这样,只有 MAP_SHARED 标志作为参数给出。
所以我现在被困住了。不知道如何调试这个。这个问题是 100% 可重现的。任何人都对这两个操作系统版本之间可能发生的变化有什么提示?
【问题讨论】:
-
如果您正在构建 64 位可执行文件,为什么不直接使用不带后缀的
mmap()?这对你的问题有什么影响吗?您确定没有分配给您指定的区域吗?如果让mmap64()选择放置内存的位置会怎样? -
最后一个参数在概要中称为
offset(mmap64()),并且:offset必须是sysconf(_SC_PAGE_SIZE)返回的页面大小的倍数。 i> 你的值是页面大小的倍数吗?在我看来,十六进制中的尾随零太少(512 的倍数,而不是 4K 或更大)。