caf*_*caf 21
SIGBUS
除了内存对齐错误之外,还有很多原因会在Linux中发生 - 例如,如果您尝试访问mmap
映射文件末尾之外的区域.
您使用的是mmap
共享内存区域或类似内容吗?
Chr*_*odd 14
如果打开未对齐的访问陷阱,您可以从未对齐的访问中获取SIGBUS,但通常在x86上关闭.如果出现某种错误,您也可以通过访问内存映射设备来获取它.
您最好的选择是使用调试器来识别故障指令(SIGBUS是同步的),并尝试查看它尝试执行的操作.
x86上的SIGBUS(包括x86_64)Linux是一种罕见的野兽.它可能出现在尝试访问mmap
ed文件的末尾或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比处理信号简单得多,特别是在多线程应用程序中。