Linux 在mmap()之后,写入返回的地址是可以的,但读取会导致系统崩溃。为什么?

Linux 在mmap()之后,写入返回的地址是可以的,但读取会导致系统崩溃。为什么?,linux,crash,kernel,mmap,itanium,Linux,Crash,Kernel,Mmap,Itanium,我想在两个进程之间共享内存。 在mmap()之后,我得到一个地址mapStart,然后我将偏移量添加到mapStart并得到mapAddr,并确保mapAddr不会超过映射页面的大小。 当我通过 memcpy((void *)mapAddr, data, size); 一切都好 但是当我读到 memcpy( &data, (void *)mapAddr, size);` 这将导致系统崩溃。 谁知道为什么? 添加一些信息:@Tony Delroy,@J-16 SDiZ mmap功能

我想在两个进程之间共享内存。
mmap()
之后,我得到一个地址
mapStart
,然后我将偏移量添加到
mapStart
并得到
mapAddr
,并确保
mapAddr
不会超过映射页面的大小。
当我通过

memcpy((void *)mapAddr, data, size);
一切都好

但是当我读到

memcpy( &data, (void *)mapAddr, size);` 
这将导致系统崩溃。
谁知道为什么?

添加一些信息:@Tony Delroy,@J-16 SDiZ
mmap功能是:

mapStart = (void volatile *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, memfd, pa_base);
系统崩溃:没有任何操作系统错误消息,控制台打印一些
MCA
info

中描述的细节只是一些想法

您的
mmap()
是否跨越具有不同属性的内存区域?这是违法的。 较旧的内核(您说的是2.6.18)允许这样做,但当您写入其中一些内核时会崩溃


请参阅以了解一些起点。如果可能,请尝试更新的内核。

至少有两个可能的问题:

在mmap()之后,我得到一个地址mapStart,然后我将偏移量添加到mapStart并得到mapAddr,并确保mapAddr不会超过映射的页面大小

必须确保Not
mapAddr
不超过映射的大小,但
mapAddr+size
。您正在尝试触摸
大小
字节,而不仅仅是一个字节

memcpy((void *)mapAddr, data, size);
memcpy( &data, (void *)mapAddr, size);
假设
数据
不是数组(这是一个合理的假设,因为您在第一行中使用它时没有地址运算符),第二行从数据指向的位置复制,但从数据开始。这很可能是一些未分配的内存,或者堆栈上的某个位置,或者其他什么。如果堆栈上没有太多内容,那么最好从堆栈末尾读入文本段,或者。。。还有别的


(如果
数据
确实是一个数组,那么它当然是等价的,但是您的代码风格会不一致。)

这里有一个疯狂的想法-为什么不显示为
mmap()准备参数的代码呢?很可能保护标志缺少保护读取,但是我们怎么知道呢?什么样的“系统崩溃”?信号故障?内核恐慌?给出错误信息。你在其他帖子中提到了IA64,这是同一个问题吗?是的,实际上这两个问题是一个问题,在IA64中都有一些与MCA相关的错误。如果您可以(1)在不使用内核模块的情况下复制它(即,这不是您的bug);(2) 在其他硬件上重现这一点(即,这不是硬件问题),在
linux上询问-ia64@vger.kernel.org
。首先:我可以确保
mapAddr+size
(程序测试)不会超过映射的大小。第二:数据是长类型,大小是8,所以我认为这不会引起问题。“第二:数据是长类型”--在这种情况下,
&data
是数据的地址,崩溃的原因正是我告诉过你的。从数据地址开始读取“一些未定义的内存范围”。删除运算符(
&
)的地址,也可以在需要指针的位置使用指针。在C中使用
long
作为指针是可行的,因为C对类型没有那么严格,但在技术上是错误的。一个指针和一个整数(如果你愿意的话,也可以是
long
)不是一回事。非常感谢你,我很抱歉没有
&
,这是我的错误。但删除“&”仍然无法解决问题。我还尝试了
printf(“%ld”,(long)(*(long*)mapAddr))也导致了系统崩溃,我使用
memcpy()
只是因为它看起来是一个正式的读取。而且,我认为如果我的程序访问“一些未定义的内存范围”,通常会导致一个段错误,程序会崩溃并退出。但我的情况是系统直接崩溃,没有任何日志消息,但只有控制台输出即MCA info。