1

:) 我正在尝试将一些遗留代码(大型程序)移植到 CentOS 7,但我遇到了障碍。代码的核心是一个相当尴尬的结构,它使用 mmap 来分配硬编码地址并将文件映射到它。该文件就像一个数据库(由一个数据库构建),并包含指向映射内存不同部分的硬编码指针。非常丑陋,但它就是这样。整个程序都是围绕这种结构构建的,没有人会资助重写。

问题出现在 mmap 行上。这以前有效,但不再在 CentOS 7 上:

mmapAddr = mmap ((void *) SMAddr, SMA_WINDOW_SIZE, PROT_READ | (readOnly ? 0 : PROT_WRITE),MAP_FILE | MAP_FIXED | MAP_SHARED, SMFileDesc, 0);

... 哪里SMAddr0x8000000,SMA_WINDOW_SIZE127926272, 并且readOnly是假的。所以基本上它试图将文件映射到0x8000000大小为 122MB 的地址。

版本之间可能发生了什么变化,我不知道。但我确实注意到它映射的文件只有 1.5MB。我不确定为什么它需要映射比文件大小更多的东西,但我知道它是必需的,而且我知道出于某种原因选择大小“122MB”有很多细微差别。

实际文件大小和分配大小之间的不匹配在过去是否很好,但现在不行了?我知道这SIGBUS意味着尝试访问无效的内存区域。鉴于 mmap 不采用任何类型的分配指针,这必须是它在内部做的事情。

我尝试捕捉和阻止SIGBUS(认为它可能会被忽略?),但程序仍然在同一个SIGBUS地方崩溃。也许我做错了。

想法?

4

1 回答 1

3

从这里1

mmap() 函数可用于映射大于对象当前大小的内存区域。映射内但超出底层对象当前端的内存访问可能会导致将 SIGBUS 信号发送到进程。这样做的原因是对象的大小可以被其他进程操纵,并且可以随时更改。实现应该告诉应用程序内存引用在可以检测到的对象之外;否则,写入的数据可能会丢失,读取的数据可能无法反映对象中的实际数据。

请注意,超出对象末尾的引用不会扩展对象,因为大多数虚拟内存硬件无法精确确定新的结尾。相反,大小可以通过 ftruncate() 直接操作。

所以最有可能的错误是你的程序试图访问位于文件之外的映射内存区域。但是, mmap 调用应该会成功。你得到哪个返回值?

于 2016-08-15T18:03:59.193 回答