对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(例如,它们太大,或者没有在页面边界上对齐)。->最有可能是我的罪魁祸首。
(从Linux2.6.12开始)长度为0。->不可能,我在调试打印中检查了长度(regionsize)值,它是0x20000。
标志既不包含map_private,也不包含map_shared,或者包含这两个值。->不能像你从我的函数调用中看到的那样,只有map_shared标志作为参数给出。
所以我现在陷入困境。不知道如何调试。这个问题是100%可重复的。有人知道这两个操作系统版本之间会发生什么变化吗?
最佳答案
将评论转换为答案(一些评论被修剪为不相关)。
如果要构建64位可执行文件,为什么不直接使用不带后缀的mmap()
?这对你的问题有什么影响吗?
然而,我认为你的问题是你所谓的regionAddr
。mmap64()
的最后一个参数在概要中称为offset
,并且:
偏移量必须是sysconf(_SC_PAGE_SIZE)
返回的页面大小的倍数。
您的值regionAddr
是页面大小的倍数吗?在我看来,十六进制中的尾随零太少了(它是512的倍数,但不是4K或更大的倍数)。
请注意,问题最初显示的值与regionAddr
不同-另请参见下面的注释。
regionAddr = 0x858521600;
和
addr = (unsigned char*) mmap64(NULL, regionSize, PROT_READ|PROT_WRITE, MAP_SHARED, FileDesc, (unsigned long long)regionAddr);
有了修改后的信息(即
regionAddr
中的值0x332C0000
或小数828521600),问题就不那么明显了。关于c - mmap64()在Red Hat 6.6中可用,但在Red Hat 7.2中不可用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38468671/