caf*_*caf 21
SIGBUS除了内存对齐错误之外,还有很多原因会在Linux中发生 - 例如,如果您尝试访问mmap映射文件末尾之外的区域.
您使用的是mmap共享内存区域或类似内容吗?
Chr*_*odd 14
如果打开未对齐的访问陷阱,您可以从未对齐的访问中获取SIGBUS,但通常在x86上关闭.如果出现某种错误,您也可以通过访问内存映射设备来获取它.
您最好的选择是使用调试器来识别故障指令(SIGBUS是同步的),并尝试查看它尝试执行的操作.
x86上的SIGBUS(包括x86_64)Linux是一种罕见的野兽.它可能出现在尝试访问mmaped文件的末尾或POSIX描述的某些其他情况之后.
但是从硬件故障来看,获取SIGBUS并不容易.也就是说,来自任何指令的未对齐访问 - 无论是否是SIMD - 通常会导致SIGSEGV.堆栈溢出导致SIGSEGV.即使访问不是规范形式的地址也会导致SIGSEGV.所有这一切都归因于#GP被提出,几乎总是映射到SIGSEGV.
现在,由于CPU异常,这里有一些获取SIGBUS的方法:
启用AC位EFLAGS,然后通过任何存储器读或写指令进行未对齐访问.有关详细信息,请参阅此讨
通过堆栈指针寄存器(rsp或rbp)进行规范违规,生成#SS.这是GCC的一个例子(编译gcc test.c -o test -masm=intel):
int main()
{
__asm__("mov rbp,0x400000000000000\n"
"mov rax,[rbp]\n"
"ud2\n");
}
小智 6
当您在 NFS(网络文件系统)上运行二进制文件并且文件发生更改时,您可能会看到 SIGBUS。请参阅https://rachelbythebay.com/w/2018/03/15/core/。
上面简要提到了这是“失败的 IO 请求”,但我将对此进行一些扩展。
常见的情况是,当您使用 ftruncate 延迟增长文件,将其映射到内存中,开始写入数据,然后耗尽文件系统中的空间。映射文件的物理空间是在页面错误时分配的,如果没有剩余,则进程会收到 SIGBUS。
如果您需要应用程序从该错误中正确恢复,则在使用 fallocate 进行 mmap 之前显式保留空间是有意义的。在fallocate调用之后处理errno中的ENOSPC比处理信号简单得多,特别是在多线程应用程序中。