mmap64()适用于Red Hat 6.6但不适用于Red Hat 7.2

时间:2016-07-19 21:15:44

标签: c linux x86-64

对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是“Invalid argument”或errno#22(EINVAL)。看一下这个引用http://linux.die.net/man/3/mmap64,我看到了EINVAL错误的3种可能性:

  1. 我们不喜欢地址,长度或偏移(例如,它们太大,或者没有在页面边界上对齐)。 - >在我的情况下,最有可能是罪魁祸首。
  2. (自Linux 2.6.12起)长度为0。 - >不可能,我在调试打印中检查了length(regionSize)值,它是0x20000。
  3. 标志既不包含MAP_PRIVATE也不包含MAP_SHARED,或包含这两个值。 - >不能这样,因为你可以从我的函数调用中看到,只给出了MAP_SHARED标志作为参数。
  4. 所以我现在卡住了。不知道如何调试这个。这个问题是100%可重复的。任何人都有关于这两个操作系统版本之间可能发生什么变化的提示吗?

1 个答案:

答案 0 :(得分:3)

将评论转移到答案中(某些评论被修剪为不相关)。

如果您正在构建64位可执行文件,为什么不简单地使用没有后缀的mmap()?这会对你的问题产生什么影响吗?

但是,我认为您的问题就是您所说的regionAddrmmap64()的最后一个参数在概要中称为offset,并且:

  

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),出现问题并不明显。