Android Native Crash奔溃

发布于:2024-03-29 ⋅ 阅读:(23) ⋅ 点赞:(0)

一.Native Crash 简介

从 Android 系统全局来说,Crash 通常分为 App/Framework Crash,Native Crash,以及 Kernel Crash。

对于 App 层或者 Framework 层的 Crash(即 Java 层面 Crash),那么往往是通过抛出未捕获异常而导致的 Crash。
至于 Kernel Crash,很多情况是发生 Kernel panic,对于内核崩溃往往是驱动或者硬件出现故障。
Native Crash,即 C/C++层面的 Crash,是介于系统 framework 层与 Linux 层之间的一层,这是本文接下来要讲解的内容。
Native Crash 发生后,系统会在路径/data/tombstones/ 下产生导致程序 Crash 的文件 tombstone_xx,并且 Google 还在 NDK 包中为我们提供了一系列的调试工具,例如 addr2line、objdump、ndk-stack。

二.为什么会产生Native Crash

常见导致Native Crash的原因有以下几种:

1. jni内部数组越界、缓冲区溢出、空指针、野指针等;

2. jni中多线程出现竞争,比如一个线程调用jni接口释放了内部一个指针,另一个线程调用另外一个jni接口还在使用这个指针;

3. Android ART发现或出现异常;

4. 其他framework、Kernel或硬件bug;

三.Tombstone信号处理机制

 函数运行在用户态,当遇到系统调用、中断或是异常的情况时,程序会进入内核态。信号涉及到了这两种状态之间的转换。

(1) 信号的接收

接收信号的任务是由内核代理的,当内核接收到信号后,会将其放到对应进程的信号队列中,同时向进程发送一个中断,使其陷入内核态。注意,此时信号还只是在队列中,对进程来说暂时是不知道有信号到来的。

(2) 信号的检测

进程陷入内核态后,有两种场景会对信号进行检测:

进程从内核态返回到用户态前进行信号检测
进程在内核态中,从睡眠状态被唤醒的时候进行信号检测
当发现有新信号时,便会进入下一步,信号的处理。

(3) 信号的处理

信号处理函数是运行在用户态的,调用处理函数前,内核会将当前内核栈的内容备份拷贝到用户栈上,并且修改指令寄存器(eip)将其指向信号处理函数。

接下来进程返回到用户态中,执行相应的信号处理函数。

信号处理函数执行完成后,还需要返回内核态,检查是否还有其它信号未处理。如果所有信号都处理完成,就会将内核栈恢复(从用户栈的备份拷贝回来),同时恢复指令寄存器(eip)将其指向中断前的运行位置,最后回到用户态继续执行进程。

至此,一个完整的信号处理流程便结束了,如果同时有多个信号到达,上面的处理流程会在第 2 步和第 3 步骤间重复进行。

(4) 常见信号量类型

在 Linux 下,每个信号的名字都以字符 SIG 开头,每个信号和一个数字编码相对应,在头文件 signum.h 中,这些信号都被定义为正整数。信号名定义路径:/usr/include/i386-linux-gnu/bits/signum.h

四.Crash日志分析

 

本文含有隐藏内容,请 开通VIP 后查看