1、信号的理解
2、Mach异常和Unix信号
Exception Type项通常会包含两个元素: Mach异常 和 Unix信号。
Exception Type: EXC_BAD_ACCESS (SIGSEGV) //EXC_BAD_ACCESS是Mach异常 ,SIGSEGV是UNIX信号
Mach异常是什么?它又是如何与Unix信号建立联系的?我们接下来一一解答:
Mach异常: Mach异常是指最底层的内核级异常,被定义在 下 。
每个thread,task,host都有一个异常端口数组,Mach的部分API暴露给了 用户态 ,用户态的开发者可以直接通过Mach API设置thread,task,host的异常端口,来捕获Mach异常,抓取Crash事件。
UNIX信号: 所有的Mach异常都在host层被转换成相应的UNIX信号,并通过threadsignal将信号投递到出错的线程。(iOS中的 POSIX API 就是通过 Mach 之上的 BSD 层实现的。)
因此: EXC_BAD_ACCESS (SIGSEGV)表示的意思是:Mach层的EXC_BAD_ACCESS异常在host层被转换成了SIGSEGV信号,并投递到出错的线程。
posix-bsd-mach层级.png
其他 : POSIX 可移植接口,Mach异常转化成UNIX信号的原因是为了兼容更为流行的POSIX标准,让不了解Mach内核的人也可以通过UNIX信号的方式来兼容开发。(即:可以通过注册signalHandler来捕获信号:)
signal(SIGABRT, SIG_DFL);
signal(SIGILL, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
Mach异常和UNIX信号都可以抓取crash事件,这两种方式哪个更好?
优选Mach异常,因为Mach异常处理会先于Unix信号处理发生,如果Mach异常的handler让程序exit了,那么Unix信号就永远不会到达这个进程了。
另外有一点需要注意的是:
因为硬件产生的信号(通过CPU陷阱)被Mach层捕获后,先产生Mach异常,然后才转换为对应的Unix信号;所以苹果为了统一机制,将操作系统和用户产生的信号(通过调用kill和pthread_kill) 也先沉