美文网首页iOS进阶之路iOSiOS笔记
iOS Mach异常和signal信号

iOS Mach异常和signal信号

作者: 阿里云云栖号 | 来源:发表于2018-03-14 09:36 被阅读641次

    本着探究下iOS Crash捕获的目的,学习了下Crash捕获相关的Mach异常和signal信号处理,记录下相关内容,并提供对应的测试示例代码。Mach为XNU的微内核,Mach异常为最底层的内核级异常,在iOS系统中,底层Crash先触发Mach异常,然后再转换为对应的signal信号。

    1. iOS Mach异常

    1.1 XNU

    Darwin是Mac OS和iOS的操作系统,而XNU是Darwin操作系统的内核部分。XNU是混合内核,兼具宏内核和微内核的特性,而Mach即为其微内核。

    Darwin操作系统和MacOS、iOS系统版本号的对应如上图所示,Mac可执行下述命令查看Darwin版本号。

    system_profiler SPSoftwareDataType

    1.2 Mach

    Mach:[mʌk],操作系统微内核,是许多新操作系统的设计基础。

    Mach微内核中有几个基础概念:

    Tasks,拥有一组系统资源的对象,允许"thread"在其中执行。

    Threads,执行的基本单位,拥有task的上下文,并共享其资源。

    Ports,task之间通讯的一组受保护的消息队列;task可对任何port发送/接收数据。

    Message,有类型的数据对象集合,只可以发送到port。

    1.3 模拟Mach Message发送

    Mach提供少量API,苹果文档介绍较少。

    // 内核中创建一个消息队列,获取对应的port

    mach_port_allocate();

    // 授予task对port的指定权限

    mach_port_insert_right();

    // 通过设定参数:

    MACH_RSV_MSG/MACH_SEND_MSG用于接收/发送mach message mach_msg();

    下述代码模拟向Mach Port发送Message,接收Message后做处理:

    首先调用createPortAndAddListener创建Mach Port;

    调用sendMachPortMessage:向已创建的Mach Port发送消息;

    执行结果示例:

    2018-02-2709:33:37.797435+0800xxx[54456:5198921]createaport: 41731

    2018-02-2709:33:37.797697+0800xxx[54456:5198921]Sendamachmessage:[100].

    2018-02-2709:33:37.797870+0800xxx[54456:5199525]Receiveamachmessage:[100],remote_port: 0,local_port: 41731,exceptioncode: 28672

    示例代码:

    1.4 捕获Mach异常

    task_set_exception_ports(),设置内核接收Mach异常消息的Port,替换为自定义的Port后,即可捕获程序执行过程中产生的异常消息。

    执行结果示例:

    2018-02-2709:52:11.483076+0800xxx[55018:5253531]createaport: 23299

    2018-02-2709:52:14.484272+0800xxx[55018:5253531]**********Makea[BAD MEM ACCESS]now. **********

    2018-02-2709:52:14.484477+0800xxx[55018:5253611]Receiveamachmessage:[2405],remote_port: 23555,local_port: 23299,exceptioncode: 1

    示例代码:

    1.5 Runloop

    Mach Port的应用不止于内核级别,在Cocoa Foundation和Core Foundation层同样有其应用,比如说:Runloop。

    Runloop sources分两类:

        Input sources

                Port-Based sources

                Custom Input sources

        Timer sources

    其中Port-Based sources即基于Mach Port,在Runloop中完成消息传递。

    上述的Mach API为内核层透出接口,Cocoa Foundation和Core Foundation层分别封装了Mach Port的接口供调用。

    2. signal信号

    signal是一种软中断信号,提供异步事件处理机制。signal是进程间相互传递信息的一种粗糙方法,使用场景:

                进程终止相关;

                终端交互;

                编程错误或硬件错误相关,系统遇到不可恢复的错误时触发崩溃机制让程序退出,比如:除0、内存写入错误等。

    这里我们主要考虑系统遇到不可恢复的错误时即Crash时,信号相关的应用。signal信号处理是UNIX操作系统机制,所以Android平台理论上也是使用的,可以基于signal来捕获Android Native Crash。

    2.1 signal注册和处理

    signal()

            #import ;

            注册signal handler;

            调用成功时,会移除signo信号当前的操作,以handler指定的新信号处理程序替代;

            信号处理函数返回void,因为没有地方给该函数返回。

    注册自定义信号处理函数,构造Crash后,发出信号并执行自定义信号处理逻辑。

            【附】:Xcode Debug运行时,添加断点,在Crash触发前,执行pro hand -p true -s false SIGABRT命令。

    (lldb) pro hand -p true -s false SIGABRT

    NAME PASS STOP NOTIFY

    =========== ===== ===== ======

    SIGABRT true false true

    2018-02-27 12:57:25.284651+0800 xxx[58061:5651844] ********** Make a 'NSRangeException' now. **********

    2018-02-27 12:57:25.294945+0800 xxx[58061:5651844] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

    2018-02-27 12:57:25.888332+0800 xxx[58061:5651844] [signal handler] - handle signal: 6

    示例代码:

    2.2 LLDB Debugger

    Xcode Debug模式运行App时,App进程signal被LLDB Debugger调试器捕获;需要使用LLDB调试命令,将指定signal处理抛到用户层处理,方便调试。

    查看全部信号传递配置:

    修改指定信号传递配置:

    2.3 可重入

    向内核发送信号时,进程可能执行到代码的任意位置,例:进程在执行重要操作,中断后可能产生不一致状态,或进程正在处理另一信号。因此要确保信号处理程序只执行可重入操作:

            写中断处理程序时,假定中断进程可能处于不可重入函数中。

            慎重修改全局数据。

    2.4 高级信号处理

    signal()函数非常基础,只提供了最低限度的信号管理的标准。而sigaction()系统调用,提供更强大的信号管理能力。当信号处理程序运行时,可以用来阻塞特定信号的接收,也可以用来获取信号发送时各种操作系统和进程状态的信息。

    示例代码:

    本文作者:红枫国度

    相关文章

      网友评论

      • 岩万方:task_set_exception_ports(),设置内核接收Mach异常消息的Port,替换为自定义的Port后,即可捕获程序执行过程中产生的异常消息。

        "内核接收Mach异常消息" 这句话没听懂
        Mach异常?不是由内核产生的吗?入门不深希望指点
      • 东风不起尘:不知所云

      本文标题:iOS Mach异常和signal信号

      本文链接:https://www.haomeiwen.com/subject/orxzfftx.html