- 浏览: 235921 次
- 性别:
- 来自: 南京
最新评论
-
baby8117628:
vc下mp3 IDv1和IDV2的读取 -
gezexu:
你好,我按照你的步骤一步步进行但是安装libvorbis的时候 ...
linux如何搭建强大的FFMPEG环境 -
ini_always:
帅哥,转载也把格式做好点,另外出处也要注明一下吧。。。
MP3文件格式解析
理解SIGBUS与SIGSEGV
Q: SIGSEGV我能理解,但有时碰上SIGBUS,这该如何理解。
A: nkwht@SMTH
nkwht用Google获取这样一些知识。有多种可能导致SIGBUS信号:
1) 硬件故障,不用说,程序员最常碰上的肯定不是这种情形。
2) Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,而是向当前进程分发SIGBUS信号。
注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。
3) 某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外
一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发SIGBUS信号。
SIGBUS与SIGSEGV信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产生core dump。
A: Marc Rochkind <rochkind@basepath.com>
SIGBUS与SIGSEGV信号的一般区别如下:
1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。
A: scz <scz@nsfocus.com> 2002-11-20
参"2.4 如何编程获取栈底地址"中如何捕获SIGBUS与SIGSEGV信号,并利用sigsetjmp、siglongjmp重获控制权。
测试表明,在x86/Linux、x86/Solaris、SPARC/Solaris平台上,越过栈底的地址访问导致SIGSEGV信号。在x86 /FreeBSD、x86/NetBSD、x86/OpenBSD平台上,越过栈底的地址访问导致SIGBUS信号,而不是SIGSEGV信号。
下面举例解释一下,什么叫未对齐的数据访问。
--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o bus bus.c
*/
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char * argv[] )
{
unsigned int i = 0x12345678;
unsigned short int *q = NULL;
unsigned char *p = ( unsigned char * )&i;
*p = 0x00;
q = ( unsigned short int * )( p + 1 );
*q = 0x0000;
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
$ ./bus
总线错误 (core dumped)
$ gdb ./bus core
GNU gdb 5.0
#0 0x1084c in main (argc=1, argv=0xffbefc54) at bus.c:16
16 *q = 0x0000;
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main> : save %sp, -128, %sp
0x10814 <main+4> : st %i0, [ %fp + 0x44 ]
0x10818 <main+8> : st %i1, [ %fp + 0x48 ]
0x1081c <main+12>: sethi %hi(0x12345400), %o1
0x10820 <main+16>: or %o1, 0x278, %o0 ! 0x12345678
0x10824 <main+20>: st %o0, [ %fp + -20 ]
0x10828 <main+24>: clr [ %fp + -24 ]
0x1082c <main+28>: add %fp, -20, %o0
0x10830 <main+32>: st %o0, [ %fp + -28 ]
0x10834 <main+36>: ld [ %fp + -28 ], %o0
0x10838 <main+40>: clrb [ %o0 ]
0x1083c <main+44>: ld [ %fp + -28 ], %o0
0x10840 <main+48>: add %o0, 1, %o1
0x10844 <main+52>: st %o1, [ %fp + -24 ]
0x10848 <main+56>: ld [ %fp + -24 ], %o0
0x1084c <main+60>: clrh [ %o0 ]
0x10850 <main+64>: clr %i0
0x10854 <main+68>: b 0x1085c <main+76>
0x10858 <main+72>: nop
0x1085c <main+76>: ret
0x10860 <main+80>: restore
End of assembler dump.
(gdb) i r pc
pc 0x1084c 67660
(gdb) i r o0
o0 0xffbefbdd -4260899
(gdb) x/3bx 0xffbefbdd
0xffbefbdd: 0x34 0x56 0x78
(gdb)
从C语言来说,执行"*q = 0x0000;"时导致SIGBUS了。从汇编指令来说,执行"clrh [%o0]"时导致SIGBUS了,寄存器%o0值为0xffbefbdd,这个地址未对齐在双字节边界上。
注意,gcc编译时并未指定-O<n>进行优化,但仍然使用clrh,而不是两次clrb。类似的汇编指令有ldw、lduh等等。有人可能碰上读操作也导致SIGBUS,觉得不可理解,其实读写导致SIGBUS没有本质区别,比如ldw只能读4字节边界上的地址。
bus.c是显式的未对齐。程序员实际最容易面对的是隐式未对齐,主要来自指针的强制类型转换。下面举例说明这种情形。
--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o other_bus other_bus.c
*/
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char * argv[] )
{
unsigned int i = 0x12345678;
unsigned short int j = 0x0000;
j = *( ( unsigned short int * )( ( ( unsigned char * )&i ) + 1 ) );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
$ ./other_bus
总线错误 (core dumped)
$ gdb ./other_bus core
GNU gdb 5.0
#0 main (argc=1, argv=0xffbefc44) at other_bus.c:13
13 j = *( ( unsigned short int * )( ( ( unsigned char * )&i ) + 1 ) );
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main> : save %sp, -120, %sp
0x10814 <main+4> : st %i0, [ %fp + 0x44 ]
0x10818 <main+8> : st %i1, [ %fp + 0x48 ]
0x1081c <main+12>: sethi %hi(0x12345400), %o1
0x10820 <main+16>: or %o1, 0x278, %o0 ! 0x12345678
0x10824 <main+20>: st %o0, [ %fp + -20 ]
0x10828 <main+24>: clrh [ %fp + -22 ]
0x1082c <main+28>: lduh [ %fp + -19 ], %o0
0x10830 <main+32>: sth %o0, [ %fp + -22 ]
0x10834 <main+36>: clr %i0
0x10838 <main+40>: b 0x10840 <main+48>
0x1083c <main+44>: nop
0x10840 <main+48>: ret
0x10844 <main+52>: restore
End of assembler dump.
(gdb) i r pc
pc 0x1082c 67628
(gdb)
因此在SPARC架构上编程,一定要留神强制类型转换,务必清楚自己正在干什么,有没有隐患。
D: yuhuan@SMTH 2004-01-30 11:48
参Linux的mmap(2)手册页
--------------------------------------------------------------------------
使用映射可能涉及到如下信号
SIGSEGV
试图对只读映射区域进行写操作
SIGBUS
试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域
Q: SIGSEGV我能理解,但有时碰上SIGBUS,这该如何理解。
A: nkwht@SMTH
nkwht用Google获取这样一些知识。有多种可能导致SIGBUS信号:
1) 硬件故障,不用说,程序员最常碰上的肯定不是这种情形。
2) Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,而是向当前进程分发SIGBUS信号。
注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。
3) 某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外
一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发SIGBUS信号。
SIGBUS与SIGSEGV信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产生core dump。
A: Marc Rochkind <rochkind@basepath.com>
SIGBUS与SIGSEGV信号的一般区别如下:
1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。
A: scz <scz@nsfocus.com> 2002-11-20
参"2.4 如何编程获取栈底地址"中如何捕获SIGBUS与SIGSEGV信号,并利用sigsetjmp、siglongjmp重获控制权。
测试表明,在x86/Linux、x86/Solaris、SPARC/Solaris平台上,越过栈底的地址访问导致SIGSEGV信号。在x86 /FreeBSD、x86/NetBSD、x86/OpenBSD平台上,越过栈底的地址访问导致SIGBUS信号,而不是SIGSEGV信号。
下面举例解释一下,什么叫未对齐的数据访问。
--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o bus bus.c
*/
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char * argv[] )
{
unsigned int i = 0x12345678;
unsigned short int *q = NULL;
unsigned char *p = ( unsigned char * )&i;
*p = 0x00;
q = ( unsigned short int * )( p + 1 );
*q = 0x0000;
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
$ ./bus
总线错误 (core dumped)
$ gdb ./bus core
GNU gdb 5.0
#0 0x1084c in main (argc=1, argv=0xffbefc54) at bus.c:16
16 *q = 0x0000;
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main> : save %sp, -128, %sp
0x10814 <main+4> : st %i0, [ %fp + 0x44 ]
0x10818 <main+8> : st %i1, [ %fp + 0x48 ]
0x1081c <main+12>: sethi %hi(0x12345400), %o1
0x10820 <main+16>: or %o1, 0x278, %o0 ! 0x12345678
0x10824 <main+20>: st %o0, [ %fp + -20 ]
0x10828 <main+24>: clr [ %fp + -24 ]
0x1082c <main+28>: add %fp, -20, %o0
0x10830 <main+32>: st %o0, [ %fp + -28 ]
0x10834 <main+36>: ld [ %fp + -28 ], %o0
0x10838 <main+40>: clrb [ %o0 ]
0x1083c <main+44>: ld [ %fp + -28 ], %o0
0x10840 <main+48>: add %o0, 1, %o1
0x10844 <main+52>: st %o1, [ %fp + -24 ]
0x10848 <main+56>: ld [ %fp + -24 ], %o0
0x1084c <main+60>: clrh [ %o0 ]
0x10850 <main+64>: clr %i0
0x10854 <main+68>: b 0x1085c <main+76>
0x10858 <main+72>: nop
0x1085c <main+76>: ret
0x10860 <main+80>: restore
End of assembler dump.
(gdb) i r pc
pc 0x1084c 67660
(gdb) i r o0
o0 0xffbefbdd -4260899
(gdb) x/3bx 0xffbefbdd
0xffbefbdd: 0x34 0x56 0x78
(gdb)
从C语言来说,执行"*q = 0x0000;"时导致SIGBUS了。从汇编指令来说,执行"clrh [%o0]"时导致SIGBUS了,寄存器%o0值为0xffbefbdd,这个地址未对齐在双字节边界上。
注意,gcc编译时并未指定-O<n>进行优化,但仍然使用clrh,而不是两次clrb。类似的汇编指令有ldw、lduh等等。有人可能碰上读操作也导致SIGBUS,觉得不可理解,其实读写导致SIGBUS没有本质区别,比如ldw只能读4字节边界上的地址。
bus.c是显式的未对齐。程序员实际最容易面对的是隐式未对齐,主要来自指针的强制类型转换。下面举例说明这种情形。
--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o other_bus other_bus.c
*/
#include <stdio.h>
#include <stdlib.h>
int main ( int argc, char * argv[] )
{
unsigned int i = 0x12345678;
unsigned short int j = 0x0000;
j = *( ( unsigned short int * )( ( ( unsigned char * )&i ) + 1 ) );
return( EXIT_SUCCESS );
} /* end of main */
--------------------------------------------------------------------------
$ ./other_bus
总线错误 (core dumped)
$ gdb ./other_bus core
GNU gdb 5.0
#0 main (argc=1, argv=0xffbefc44) at other_bus.c:13
13 j = *( ( unsigned short int * )( ( ( unsigned char * )&i ) + 1 ) );
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main> : save %sp, -120, %sp
0x10814 <main+4> : st %i0, [ %fp + 0x44 ]
0x10818 <main+8> : st %i1, [ %fp + 0x48 ]
0x1081c <main+12>: sethi %hi(0x12345400), %o1
0x10820 <main+16>: or %o1, 0x278, %o0 ! 0x12345678
0x10824 <main+20>: st %o0, [ %fp + -20 ]
0x10828 <main+24>: clrh [ %fp + -22 ]
0x1082c <main+28>: lduh [ %fp + -19 ], %o0
0x10830 <main+32>: sth %o0, [ %fp + -22 ]
0x10834 <main+36>: clr %i0
0x10838 <main+40>: b 0x10840 <main+48>
0x1083c <main+44>: nop
0x10840 <main+48>: ret
0x10844 <main+52>: restore
End of assembler dump.
(gdb) i r pc
pc 0x1082c 67628
(gdb)
因此在SPARC架构上编程,一定要留神强制类型转换,务必清楚自己正在干什么,有没有隐患。
D: yuhuan@SMTH 2004-01-30 11:48
参Linux的mmap(2)手册页
--------------------------------------------------------------------------
使用映射可能涉及到如下信号
SIGSEGV
试图对只读映射区域进行写操作
SIGBUS
试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域
发表评论
-
内存屏障
2010-02-26 11:03 1508处理器的乱序和并发执行 目前的高级处理器,为了提高内部逻辑元 ... -
函数调用堆栈分析
2010-02-26 10:53 1383理解调用栈最重要的两 ... -
mtrace检测内存泄露
2010-02-25 09:50 1091[url] http://math.acadiau.ca/AC ... -
c语言编程之字符串操作
2010-02-25 09:41 8631. //在s串中查找与s1相匹配的字符串,找到后用 ... -
linux C 链接库 so制作及调用[转]
2010-02-24 16:26 2579文章分类:C++编程 [文章作者:陈毓端 若转载请标注原文链 ... -
mtrace的使用
2010-02-24 16:02 1313对于内存溢出之类的麻烦可能大家在编写指针比较多的复杂的程序的时 ... -
单片机的C语言中位操作用法(转
2010-02-24 14:27 2214单片机的C语言中位操作用法 作者:郭天祥 在对单处机进 ... -
Linux下的itoa函数
2010-02-21 17:55 1766上篇文章说到linux需要it ... -
va_list、va_start、va_arg、va_end的原理与使用
2010-02-05 10:34 29031. 概述 由于在C语言中没有函数重载,解 ... -
快速排序(quickSort)
2010-02-04 10:50 8681. #include <stdio.h> ... -
C问题---itoa函数
2010-02-04 10:36 1048------------------------------ ... -
itoa函数及atoi函数
2010-02-04 10:35 1313C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点 ... -
结构体零长度数组的作用
2010-02-04 10:21 1375在一些 C 语言编写的代码中,有时可以看到如下定义的结构: ... -
优化C代码常用的几招
2010-02-04 10:14 776性能优化方面永远注意8 ... -
我经常去的网站
2010-02-03 17:53 1623MFC相关网站 www.codeproject.com ht ... -
可重入函数与不可重入函数
2010-02-03 16:35 932原文地址:http://blog.chin ... -
linux线程池及其测试
2010-02-03 16:32 2362/*----------------------------- ... -
哈夫曼编码
2010-02-03 16:26 1317本文描述在网上能够找到的最简单,最快速的哈夫曼编码。本方法不使 ... -
优化变成了忧患:String.split引发的“内存泄露”
2010-02-01 17:39 1118一直赞叹Sun对待技术的 ... -
锁无关的(Lock-Free)数据结构——在避免死锁的同时确保线程
2010-01-26 14:47 907http://hi.baidu.com/%5F%E2%64%5 ...
相关推荐
- **SIGBUS**:总线错误。 - **SIGSEGV**:段违例,进程试图访问其虚拟地址空间之外的内存。 - **SIGSYS**:系统调用错误。 - **SIGPIPE**:向非读端口写数据。 - **SIGALRM**:定时器信号。 - **SIGTERM**:软件...
`signal()`函数有两个参数:`signum`是信号编号,例如`SIGBUS`表示 Bus Error;`handler`是一个函数指针,用于指定接收信号时执行的函数。实验中定义了一个简单的信号处理函数,当接收到`SIGBUS`信号时,输出一条...
### Linux信号机制与Signal详解 #### 一、信号机制的基本概念 信号是Linux操作系统中用于进程间通信的重要机制之一,其本质上是一种软中断信号。它主要用于通知进程发生了异步事件,而不涉及具体的数据传递。在...
"Linux 信号signal处理机制" 本文详细介绍了Linux信号机制的基本概念、Linux对信号机制的大致实现方法、如何使用信号,以及有关信号的几个系统调用。信号机制是进程之间相互传递消息的一种方法,信号全称为软中断...
Linux支持多种信号,包括POSIX.1标准定义的信号(如SIGHUP、SIGINT、SIGKILL等)以及一些非标准信号(如SIGBUS、SIGPOLL等)。每种信号都有特定的值和处理动作,比如SIGINT(2)通常代表键盘中断,SIGKILL(9)则是...
在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点在程序中可以... 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SI
signal(SIGBUS, sig_handler); ``` 然后向进程发送SIGBUS信号,触发处理函数执行。 3. **消息队列(Message Queue)** 消息队列是另一种IPC机制,允许进程以消息为单位进行数据交换。它提供了更灵活的数据结构和...
const char data[] = "Pipe Test Program"; int real_read, real_write; memset((void*)buf, 0, sizeof(buf)); /* 创建管道 */ if (pipe(pipe_fd) ) { printf("pipe create error\n"); exit(1); } /* ...
printf("Received signal %d\n", signo); exit(1); } int main() { struct sigaction act; // 初始化sigaction结构体 act.sa_handler = my_signal_handler; act.sa_flags = 0; sigemptyset(&act.sa_mask); ...
它是一个小型的C语言编译器,由Infocompilerbook的作者在www.sigbus.info上介绍。通过参与9cc的实现,你可以深入理解编译原理,掌握如何将高级语言(如C)转换为机器可执行代码的基本步骤。 编译器是计算机科学中的...
2. **SIGBUS(signal 7)**:非法地址访问,但与SIGSEGV不同之处在于访问的地址虽在进程地址空间内,但未按字节对齐(例如,访问未被2或4整除的地址)。另一种情况是在使用mmap映射文件后,文件被截断但仍尝试访问已...
7. **SIGBUS**:总线错误(Bus Error)信号,当进程尝试访问不正确对齐的内存地址或执行了无效的内存操作时触发。 8. **SIGFPE**:浮点异常(Floating Point Exception)信号,当发生致命的算术运算错误时发出,比如...
SIGBUS信号通常表示访问了无效内存地址,但在实验中,可能是用来演示信号处理。 4. **消息队列(Message Queue)** 消息队列允许进程之间传递结构化数据,且支持多个进程同时读写。使用`msgget()`创建消息队列,`...
在深入了解Python进程的信号通讯之前,首先需要明白什么是信号(signal)。在操作系统层面,信号是一种软件中断的形式,用以实现进程之间的通讯。当一个进程接收到一个信号时,它会暂停当前的程序执行流程,转而处理...
在Linux操作系统中,信号(Signal)是一种进程间通信机制,用于通知进程发生了特定事件或异常。这份名为"Linux信号列表[文].pdf"的文档详细列出了Linux系统中支持的各种信号,这些信号对于软件开发人员理解和调试...