和你一起终身学习,这里是程序员Android
本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:
一、Kernel Exception概述
二、Kernel空间布局
三、printk 概述
四、AEE db log机制
五、前期异常处理
六、die()流程
七、panic()流程
八、nested panic
一、Kernel Exception(KE)概述
Android OS由3层组成,最底层是Kernel,上面是Native bin/lib,最上层是Java层:
Android OS 3层结构
任何软件都有可能发生异常,比如野指针,跑飞、死锁等等。
当异常发生在kernel层,我们就叫它为KE(kernel exception),同理,发生在Native就是NE,Java层就是JE。这篇文章仅关注底层的KE。
1. KE类别
kernel有以下2种(oops、panic)崩溃类别
oops (类似assert,有机会恢复)
oops是美国人比较常有的口语。就是有点意外,吃惊,或突然的意思。内核行为表现为通知感兴趣模块,打印各种信息,如寄存器值,堆栈信息…
当出现oops时,我们就可以根据寄存器等信息调试并解决问题。
/proc/sys/kernel/panic_on_oops为1时导致panic。我们默认设置为1,即oops会发生panic。
panic
Panic – 困惑,恐慌,它表示Linux kernel遇到了一个不知道该怎么继续的情况。内核行为表现为通知感兴趣模块,死机或者重启。
在kernel代码里,有些代码加了错误检查,发现错误可能直接调用了panic(),并输出信息提供调试
2. KE常用调试方法
凡是程序就有bug。bug总是出现在预料之外的地方。据说世界上第一个bug是继电器式计算机中飞进一只蛾子,倒霉的飞蛾夹在继电器之间导致了计算机故障。由于这个小虫子,程序中的错误就被称为了bug。
有Bug就需要Debug,而调试是一种很个性化的工作,十个人可能有十种调试方法。但从手段上来讲,大致可分为两类,在线调试 (Online Debug) 和离线调试 (Offline Debug).
3.在线调试
Online debug, 指的是在程序的运行过程中监视程序的行为,分析是否符合预期。通常会借助一些工具,如GDB和Trace32等。有时候也会借助一些硬件设备的协助,如仿真器/JTAG,但是准备环境非常困难,而且用起来也很麻烦,除非一些runtime问题需要外很少使用。
4.离线调试,
Offline debug, 指的是在程序的运行中收集需要的信息,在Bug发生后根据收集到的信息来分析的一种手段。通常也分为两种方式,一种是Logging,一种是Memory Dump。
Logging
日志或者相关信息的收集,可以比较清晰的看到代码的执行过程,对于逻辑问题是一种有效的分析手段,由于其简单易操作,也是最为重要的一种分析手法。
Memory Dump
翻译过来叫做内存转储,指的是在异常发生的时刻将内存信息全部转储到外部存储器,即将异常现场信息备份下来以供事后分析。是针对CPU执行异常的一种非常有效的分析手段。在Windows平台,程序异常发生之后可以选择启动调试器来马上调试。在Linux平台,程序发生异常之后会转储core dump,而此coredump可以用调试器GDB来进行调试。而内核的异常也可以进行类似的转储。
二、Kernel空间布局
在分析KE前,你要了解kernel内存布局,才知道哪些地址用来做什么,可能会是什么问题。
在内核空间中存在如下重要的段:
1. vmlinux代码/数据段:
任何程序都有TEXT(可执行代码),RW(数据段),ZI段(未初始化数据段),kernel也有,对应的是.text,.data,.bss
2.module区域:
kernel可以支持ko(模块),因此需要一段空间用于存储代码和数据段。
3. vmalloc区域:
kernel除了可以申请连续物理地址的内存外,还可以申请不连续的内存(虚拟地址是连续的),可以避免内存碎片化而申请不到内存。
4. io map区域:
留给io寄存器映射的区域,有些版本没有io map区域而是直接用vmalloc区域了。
5.memmap:
kernel是通过page结构体描述内存的,每一个页框都有对应的page结构体,而memmap就是page结构体数组。
还有其他段小的段没有列出来,可能根据不同的版本而差别。
6. ARM64bit kernel布局
目前智能机已进入64bit,因此就存在32bit布局和64bit布局,下面一一讲解。
ARM64可以使用多达48bit物理、虚拟地址(扩充成64bit,高位全为1或0)。对linux kernel来讲,目前配置为39bit的kernel空间。
由于多达512GB的空间,因此完全可以将整个RAM映射进来,0xFFFFFFC000000000之后就是一一映射了,就无所谓high memory了。
vmalloc区域功能除了外设寄存器也直接映射到vmalloc了,就没有32bit布局里的IO map space了。
不同版本的kernel,布局稍有差别:
kernel-3.10
kernel-3.10
= kernel-3.18 && < kernel-4.6