SIGBUS, 0, “unknown32” }, { do_bad, SIGBUS, BUS_ADRALN , SIGBUS, 0, “unknown36” }, { do_bad, SIGBUS , SIGBUS, 0, “unknown41” }, { do_bad, SIGBUS , SIGBUS, 0, “unknown46” }, { do_bad, SIGBUS , SIGBUS, 0, “unknown51” }, { do_bad, SIGBUS
0: always panic on uncorrected errors, log corrected errors 1: panic or SIGBUS on uncorrected errors, log corrected errors 2: SIGBUS or log uncorrected errors (if possible), log corrected errors 3: never panic or SIGBUS, log all errors (for testing only) mce-inject使用 mce-inject的使用方法也很简单,不过在使用前要现将tolerate
6.3 核心案例 3:总线错误 —— 触发 SIGBUS 信号(10 号) SIGBUS信号(Bus error)的产生条件是:进程访问的内存地址是有效的,但访问方式不正确(如对齐错误、内存映射失败) 实战:内存对齐错误触发 SIGBUS 信号 在某些 CPU 架构(如 ARM)中,访问未对齐的内存地址会触发 SIGBUS 信号。 信号处理函数 void sigbus_handler(int signum) { cout << "捕获到信号:" << signum << "(SIGBUS),总线错误(内存对齐错误)!" 信号的处理函数 signal(SIGBUS, sigbus_handler); sleep(1); // 内存对齐错误:char数组的地址是1字节对齐,强制转换为int*(4 捕获到信号:10(SIGBUS),总线错误(内存对齐错误)!
但要注意的是,mmap有个坑,如果文件在映射期间被其他进程修改了,可能会收到SIGBUS信号导致程序崩溃。所以在生产环境中,一定要做好异常处理。 错误处理:使用mmap时要特别注意SIGBUS信号,文件被截断或者磁盘空间不足都可能触发这个信号。 // 简单的信号处理 void sigbus_handler(int sig) { printf("SIGBUS caught, file may have been truncated\n") ; // 做一些清理工作 } signal(SIGBUS, sigbus_handler); 不同技术的性能对比 我在测试环境中做过一些性能对比,传输1GB文件的结果大概是这样的: • 传统read
2.Signal层面的crash 除了OC层面的异常捕获之外,很多内存错误、访问错误的地址产生的crash则需要利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数 SIGBUS:非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。 NSString *reason = [exception reason]; NSString *name = [exception name]; } 1.2 Appdelegate中注册SIGABRT, SIGBUS SignalExceptionHandler); signal(SIGSEGV, SignalExceptionHandler); signal(SIGFPE, SignalExceptionHandler); signal(SIGBUS
但是使用mmap``mmap``map``SIGBUS``SIGBUS``coredump 通常我们使用以下解决方案避免这种问题: 为SIGBUS信号建立信号处理程序当遇到SIGBUS信号时,信号处理程序简单地返回 这样在程序访问非法内存并且被SIGBUS杀死之前,你的write系统调用会被中断。write会返回已经写入的字节数,并且置errno为success。
例如,当你的程序map了一个文件,但是当这个文件被另一个进程截断(truncate)时, write系统调用会因为访问非法地址而被SIGBUS信号终止。 SIGBUS信号默认会杀死你的进程并产生一个coredump,如果你的服务器这样被中止了,那会产生一笔损失。 通常我们使用以下解决方案避免这种问题: 1. 为SIGBUS信号建立信号处理程序 当遇到SIGBUS信号时,信号处理程序简单地返回,write系统调用在被中断之前会返回已经写入的字节数,并且errno会被设置成success,但是这是一种糟糕的处理办法 这样在程序访问非法内存并且被SIGBUS杀死之前,你的write系统调用会被中断。write会返回已经写入的字节数,并且置errno为success。
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS SIGBUS: 当一个进程被发送SIGBUS信号时,是因为该进程导致了一个总线错误,通常这些总线错误是由于进程试图使用假物理地址或进程的内存对齐设置不正确造成的。 示例 要显示所有可用信号,查看信号的详细信息可以使用man命令,例如信号7 SIGBUS即使用man 7 signal。 kill -l 在表格中列出可用的信号名称和编号。
Native崩溃使用信号(singal)机制返回信息: Android native崩溃产生常见信号大致有以下几类: SIGABRT SIGSTKFLT SIGTARP SIGSEGV SIGBUS SIGSEGV 非法内存操作,与下面的SIGBUS不同,是对合法地址的非法访问,比如访问没有读权限的内存,向没有写权限的地址写数据等。 当前执行的指令访问的内存地址无访问权限(读、写、执行) SEGV_MAPERR: 字符串溢出:寄存器中不够存储字符串长度 空对象:底层某个对象null了 PC跑飞:一般是程序(PC寄存器)跑飞或者栈(SP寄存器)被破坏 SIGBUS
fault_type, VM_FAULT_OOM)) return "OOM"; else if(vm_fault_contains(fault_type, VM_FAULT_SIGBUS )) return "SIGBUS"; else if(vm_fault_contains(fault_type, VM_FAULT_MINOR)) return
kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。 在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP 不能恢复至默认动作的信号有:SIGILL,SIGTRAP 默认会导致进程流产的信号有:SIGABRT,SIGBUS,
我们运行如下命令,可看到Linux支持的信号列表: ~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。 在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP 不能恢复至默认动作的信号有:SIGILL,SIGTRAP 默认会导致进程流产的信号有:SIGABRT,SIGBUS,
我自己常碰到的是 char *p = NULL; *p = 1;會產生SIGSEGV對同一個指針free() 2次可能會產生SIGABRTaddress alignment可能會導致SIGBUS $ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE9) SIGKILL 10 7) SIGBUS 非法地址, 包括內存地址對齊(alignment)出錯。比如訪問一個四個字長的整數, 但其地址不是4的倍數。 在以上列出的信號中,程序不可捕獲、阻塞或忽略的信號有:SIGKILL,SIGSTOP 不能恢復至默認動作的信號有:SIGILL,SIGTRAP 默認會導致進程流產的信號有:SIGABRT,SIGBUS,
此时write系统调用会被进程接收到的SIGBUS信号中断,因为当前进程访问了非法内存地址。 对SIGBUS信号的默认处理是杀死当前进程并生成dump core文件——而这对于网络服务器程序而言不是最期望的操作。 有两种方式可用于解决该问题: 第一种方式是为SIGBUS信号设置信号处理程序,并在处理程序中简单的执行return语句。 这样,在write调用访问非法内存地址、并被随后接收到的SIGBUS信号杀死之前,write系统调用就被RT_SIGNAL_LEASE信号中断了。 如果进程没有为SIGBUS注册任何信号处理函数的话,sendfile系统调用返回被信号中断前已发送的字节数,并将全局变量errno置为成功。
7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。 在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP 不能恢复至默认动作的信号有:SIGILL,SIGTRAP 默认会导致进程流产的信号有:SIGABRT,SIGBUS, 终止进程 中断进程 SIGQUIT 建立CORE文件终止进程,并且生成core文件 SIGILL 建立CORE文件 非法指令 SIGTRAP 建立CORE文件 跟踪自陷 SIGBUS
kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 7) SIGBUS非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。 在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP不能恢复至默认动作的信号有:SIGILL,SIGTRAP默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE
-l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 非来自终端的停止信号 SIGTSTP 18,20,24 Stop 来自终端的停止信号 SIGTTIN 21,21,26 Stop 后台进程读终端 SIGTTOU 22,22,27 Stop 后台进程写终端 SIGBUS
1234 did not exit, sending another SIGHUP notice Normal but significant condition 一般重要情况 httpd: caught SIGBUS
3 信号与异常处理 存储映射 I/O 的使用过程中可能引发的信号主要包括 SIGSEGV 和 SIGBUS。 SIGSEGV:当映射区被设为只读,而进程尝试写入该映射区时触发。 SIGBUS:当映射区的某一部分已不存在时触发,如文件被截断导致映射区域超出文件范围。
SIGBUS与SIGSEGV的区别 SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。