一,Bus Error究竟是指什么
Bus Error,即总线错误。
引发原因:
CPU处于性能方面的考虑,要求对数据进行访问时都必须是地址对齐的。如果发现进行的不是地址对齐的访问,就会发送SIGBUS信号给进程,使进程产生
core
dump。RISC包括SPARC(一种微处理器架构)都是这种类型的芯片。x86系列CPU都支持不对齐访问,也提供了开关禁用这个机制。x86架构不
要求对齐访问的时候,必定会有性能代价。例如,对int的访问应该是4字节对齐的,即地址应该是4的倍数,对short则是2字节对齐的,地址应该是2的
倍数。
Bus Error也有可能是因为机器物理问题或者访问无效物理地址,但这种情况非常少见。
Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,而是向当前进程分发SIGBUS信号。
注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。
SIGBUS与SIGSEGV信号的一般区别如下:
1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。
二,例子程序:
1 int main(){
2
3
4
5
6 #if defined(__GNUC__)
7 # if defined(__i386__)
8 /* Enable Alignment Checking on x86 */
9 __asm__("pushf\norl $0x40000,(%esp)\npopf");
10 # elif defined(__x86_64__)
11 /* Enable Alignment Checking on x86_64 */
12 __asm__("pushf\norl $0x40000,(%rsp)\npopf");
13 # endif
14 #endif
15
16
17
18
19
20
21
22
23
24 short array[16];
25
26 int * p = (int *) &array[1];
27 *p = 1;
28
29 return 1;
30 }
short类型大小为2个字节,其地址必是2的倍数。而对于int指针来说,能够使用以访问数据的地址应该是4的倍数,转化arrary[1]的地址为int *并访问,系统会发出SIGBUS信号,导致程序崩溃。
wiki上的例子:
http://en.wikipedia.org/wiki/Bus_error#Bus_error_example
#include <stdlib.h>
int
main(
int
argc,
char
**
argv)
{
int
*
iptr;
char
*
cptr;
#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__(
"pushf\n
orl $0x40000,(%esp)\n
popf"
)
;
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__(
"pushf\n
orl $0x40000,(%rsp)\n
popf"
)
;
# endif
#endif
/* malloc() always provides aligned memory */
cptr =
malloc(
sizeof
(
int
)
+
1)
;
/* Increment the pointer by one, making it misaligned */
iptr =
(
int
*
)
++
cptr;
/* Dereference it as an int pointer, causing an unaligned access */
*
iptr =
42
;
return
0
;
}
$ gcc -ansi sigbus.c -o sigbus
$ ./sigbus
Bus error
$ gdb ./sigbus
(gdb) r
Program received signal SIGBUS
, Bus error.
0x080483ba in main ()
(gdb) x/i $pc
0x80483ba <main+54>: mov DWORD PTR [eax],0x2a
(gdb) p/x $eax
$1 = 0x804a009
(gdb) p/t $eax & (sizeof(int) - 1)
$2 = 1
三,编译器和硬件平台相关性
上述已经描述,对于x86平台,默认允许非对齐访问,只不过会有性能代价。开启检测可以使用上述代码中的宏。
这段程序如果用Sun Studio编译器的话,运行就没有问题。这是因为Sun
Studio默认对32位编译使用的参数是-xmemalign=8i,其中i选项设置明确指明不产生SIGBUS信号。
不过如果编译成64位程序,Sun Studio使用的-xmemalign=8s,其中s选项设置意味对这种非对齐访问产生SIGBUS信号,则仍旧会遇到这个错误。
如果坚持在SPARC上使用GCC去编译这种代码,可以如下进行:
GCC有一个Type Attributes特性,例如在需人工对齐的变量后加上:__attribute__ ((aligned (4))); 其意义就是指定偏移量为4的倍数。比如:
short array[10] __attribute__ ((aligned (4)));
不过这个属性只对Linker连接器可见的变量有效,也就是说对local
variable无效。而且这种特性作用粒度比较大,比如这里只对第一个元素有作用,并不为数组的每个成员设置偏移量。如果一定要针对local
variable或者数组的每个成员进行偏移量设置,可以使用union类型:
union {
short s;
int i;
}
分享到:
相关推荐
linux驱动 bus-device-driver模型
spring-cloud-config + spring-cloud-bus-amqp实现分布式集群配置动态更新,可更新实例对象,包含源码包+Rabbitmq安装包和安装说明
AC'97代码,文档---(APB BUS) AC'97代码,文档---(APB BUS)
Laravel开发-laravel-command-bus Laravel命令总线
ABB智能建筑控制系统 - i-bus (智能家居应用方案)pdf,ABB智能建筑控制系统 - i-bus (智能家居应用方案):世界500强ABB集团是总部设在瑞士苏黎世的百年企业、电气与自动化行业的领导品牌。 i-bus?是ABB集团专为全球...
施耐德共直流母线-ATV32-LXM32-DC-buspdf,施耐德共直流母线-ATV32-LXM32-DC-bus
ABB智能建筑控制系统 - i-bus EIB/KNXpdf,ABB智能建筑控制系统 - i-bus EIB/KNX:i-bus 系统中受控的负载直接与控制系统的驱动器相连,所有传感器(如:智能面板、移动感应器、光亮传感器)和驱动器(如:开关驱动器...
Linux驱动程序开发-设备驱动模型 Linux2.6设备驱动模型的基本元素是Class、Bus、Device、Driver,下面我们分别介绍各个部分。
IE-BUS CAN 样例程序
项目驱动CAN-bus现场总线基础教程,CAN-bus通信网络的完整实现来展现CAN-bus各方面知识。
三菱FX5,FX5U相关手册
行业制造-电动装置-M-BUS总线数据解调电路.zip
藏经阁-Free-Fall-Hacking-Tesla-From-Wireless-To-CAN-Bus
Laravel开发-laravel-command-bus .zip
I2S代码,文档---(APB BUS)
ng-event-bus 角为基于RxJS的消息/事件总线服务的应用程序的启发 。 将其注入您的应用程序模块。 您可以检查 。 安装 npm install --save ng-event-bus 用法 首先,将其导入: import { NgEventBus } from 'ng-...
mobx-event-bus· Tiny库允许组件之间进行发布-订阅式通信,而无需组件之间进行显式注册。 安装 npm install mobx-event-bus --save 用法 基本的 import { eventBus , subscribe } from 'mobx-event-bus' class ...
ABB智能建筑控制系统 - i-bus传感器pdf,ABB智能建筑控制系统 - i-bus传感器
主要介绍周立功的CAN-bus开发套件、接口卡、转换器、分析工具等