Android内核开发:学会分析系统的启动log

本文是《Android内核开发》系列的第八篇文章,本文主要关注如何分析Android系统的启动log,学会通过搜索重要的TAG标签,找到Android启动过程中的重要节点。

要学会分析系统的启动log信息,首先得了解Android系统的启动过程,建议先阅读《Android内核开发:图解Android系统的启动过程》这篇文章,它详细介绍了Android系统的启动过程。其次,你需要知道如何抓取系统启动log信息,建议阅读《Android内核开发:如何统计系统启动时间》这篇文章,它详细地介绍了如何抓取系统的启动log信息。

本文在这2篇文章的基础上,进一步介绍如何深入地分析系统启动log信息,找出Android启动启动过程中每一个部分所消耗的具体时间节点。

首先,我们给出一张比较全面的Android系统启动图(来自Embeded Android):

根据上述Android的启动框图,我们可以顺序地列出Android系统启动中涉及的几个关键步骤:

(1) Linux内核的启动

(2) Init程序启动,并启动各个本地服务(如 healthd, debuggerd等)

(3) Zygote进程启动

(4) Zygote进程初始化工作(preload class/resource)

(5) SystemServer进程启动,并启动各个Java服务(如 ActivityManager, PackageManager等 )

(7) 启动结束的标志点

如果我们能够从启动log信息中找出上述这些关键步骤的时间节点,也就可以很清晰地得到Android系统启动过程中各个模块消耗的时间了,在做系统启动优化时,也就知道该去优化哪些耗时的模块了,同样,在分析系统启动bug的时候,也就知道到底哪里出了问题了。

下面,我们以高通的APQ8064开发板(Android 4.4.2)的启动log信息为例来分析(这些log文件上传到我的Github上了:https://github.com/Jhuster/AOSP/tree/master/logs/APQ8064),其实各个Android系统都有类似的log输出,我们只需重点掌握关键节点的TAG和分析方法。

1.  配置系统的log输出

(1) 在内核log信息中打印出时间信息

在Linux kernel源码树中执行 make menuconfig,勾选下面的选项:

"Kernel hacking" -> "Show timing information on printks"

(2) 将init进程的详细log输出到dmesg文件中

修改/system/core/rootdir/init.rc,把loglevel从3改为7

2.  抓取系统启动的log信息

前面的文章已经介绍过,Android系统启动的log分为Linux内核的log和Android Logger系统的log,

抓取的方法如下:

$ adb shell dmesg > dmesg.txt

$ adb logcat -d -v time -b "main"   >  main.txt

$ adb logcat -d -v time -b "system" >  system.txt

$ adb logcat -d -v time -b "events" >  events.txt

3.  分析log信息

(1) Linux内核的启动

Linux内核启动的log都位于dmesg.txt文件中,从log文件开始直到出现下面这条消息则标志着Linux内核已经完成了启动:

"Freeing init memory"

因此,我们从dmesg.txt文件中即可得到APQ8064开发板的Linux内核启动只用了6.613s,如图所示:

(2) Init程序启动,并启动各个本地服务(如 healthd, debuggerd等)

Init程序的log信息也位于dmesg.txt文件中,我们可以通过检索“init”找到该程序的打印消息。

通过检索“init starting”,我们可以找到init进程启动了哪些本地服务,如:

(3) Zygote进程启动

zygote进程是在init进程中启动的,因此,我们从上面init进程的输出log中,检索"zygote"就可以找到zygote进程何时启动的,如图所示:

(4) Zygote进程初始化工作(preload class/resource)

Zygote进程所输出的log信息被放到/dev/log/main文件中了,因此,我们需要检索main.txt得到Zygote的log信息。

由于后续所有的Android应用程序都是从Zygote进程fork出来的,Android系统为了提高应用程序的启动速度,会在Zygote进程初始化过程中加载一些常用的java class和资源文件到进程的内存中,从而共享常用的class和resourse资源。这个过程我们可以通过检索"preload"标签得到这个过程所消耗的时间,如图所示:

(5) SystemServer进程启动,并启动各个Java服务(如 ActivityManager, PackageManager等 )

Zygote完成了初始化工作后就启动SystemServer进程了,SystemServer进程的log信息被放到了/dev/log/system文件中了,因此,我们需要检索system.txt文件得到SystemServer的log信息,如图所示:

(7) 启动结束的标志点

《Android内核开发:如何统计系统启动时间》这篇文章已经详细地介绍了如何找到启动结束的时间,这里选取其中一种方法再复述一遍,就是检索dmesg文件的 "boot_completed" 标志,如图所示,我们知道了整个系统一共耗时29.913s完成启动:

4. 小结

关于深度解析Android系统的启动log信息就介绍到这里了,有任何疑问或者建议欢迎留言或者来信[email protected]交流,或者关注我的新浪微博@卢_俊 获取最新的文章和资讯。

时间: 2024-08-02 06:56:29

Android内核开发:学会分析系统的启动log的相关文章

Android内核开发:图解Android系统的启动过程

本文是<Android内核开发>系列的第六篇文章,前面的几篇文章介绍了Android内核开发相关的基础知识,包括:Android源码的下载.版本和分支介绍.编译和烧写等等,从本文起就要开始真正地进行Android内核的学习及实战了. 学习任何软硬件系统,研究系统启动过程都是一种非常有效地起步手段,搞Android内核开发也不例外.网上有很多文章对Android启动相关代码进行分析和走读,大家可以先搜索阅读一下,我个人更喜欢更加直观的方式去理解未知的东西,包括图.表.系统输出的log信息等等,因

Android内核开发:为什么刷机后系统第一次启动会很慢?

在做Android内核开发的过程中,我们会发现,每次编译完系统源码,烧录到设备/手机中后,第一次启动都会很慢很慢,要好几分钟甚至十几分钟,为什么会出现这样的现象呢?系统刷机后第一次启动与后面再次启动有什么不同呢? 要解答这个问题,首先我们需要了解一下Android Dalvik虚拟机,以及Dalvik-cache. 由于嵌入式设备内存有限.CPU处理器不够强大.功耗敏感等原因,Google没有使用标准的JVM虚拟机,而是为Android单独开发了Dalvik虚拟机. Dalvik虚拟机与JVM虚

Android内核开发:系统启动速度优化

在学习新知识的过程中,我一直很推荐结合实战任务去学习,只有经历实战,才能加深对理论知识的理解.<Android内核开发>系列已经写了八篇了,本文就结合前面的内容,给大家布置一个实战任务: 优化Android系统的启动速度. 这里我简单介绍一下优化的基本思路和涉及的文件,具体细节由大家自己在实践去摸索,提高自己Google能力和解决问题的能力. Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android

Android内核开发:如何统计系统的启动时间

本文是<Android内核开发>系列的第七篇文章,通过上一篇文章<Android内核开发:图解Android系统的启动过程>我们大致了解了Android系统的启动过程,那么本文就从实践的角度,简单介绍一下如何统计Android系统的启动时间. 这里所说的统计系统的启动时间,并不是简单地用秒表和肉眼来统计,而是通过分析系统输出的log信息来统计,这样才显得更加专业. 首先了解2个概念: (1) Android是基于Linux内核的系统,因此Android的启动过程是分为两个阶段的,第

Android内核开发:系统编译输出的镜像文件

本文是<Android内核开发>的第四篇文章,主要介绍一下源码编译输出的几个重要的镜像文件,这里把bootloader源码和Linux内核源码的编译输出也算在其中,因为毕竟Android系统缺少了这两个部分在设备上也是跑不起来的. 1. MLO, u-boot.img 任何操作系统的启动,都离不开"引导程序",比如桌面Windows系统的BIOS.桌面Linux系统常用的是Grub,而在嵌入式系统中,这个引导程序通常叫做"bootloader",它通常由

Android内核开发:系统分区与镜像文件的烧写

本文是<Android内核开发>系列的第五篇文章,本文重点介绍如何把编译输出的镜像文件烧写到Android设备中. 玩过刷机的朋友肯定对fastboot这个工具并不陌生,它是Android SDK中提供的一种开发工具,支持通过USB线将手头的镜像文件更新/烧录到Android设备中,常用的fastboot烧录过程如下: fastboot flash boot boot.img fastboot flash system system.img fastboot flash userdata us

Android内核开发:序

转眼间我的<Android开发实践>系列文章已经写了三十多篇了,很多文章写得还是蛮用心的,所以很感谢51CTO的编辑们经常加精和推荐.我发现通过写作的确可以逼着自己去深入了解一些平时开发中并不会去挖掘的细节,这对自己帮助挺大的,后面遇到好的主题我还会继续写下去. 以前写的<Android开发实践>这个系列主要偏向Android应用层的开发,从一开始学习Android就计划好了要往底层深入,如今正好在工作中有机会涉及Android源码开发,因此,再开辟一个系列,就叫<Andro

Android内核开发:从源码树中删除出厂的app应用

本文是<Android内核开发>系列的第十一篇文章,本文重点介绍如何从Android源码中删除出厂的app应用. 上一篇文章中提到过,系统出厂的app应用,其实就是被安装到/system分区的app,这些app在Android源码树中被编译后打包到了system.img镜像中,系统启动时,以只读的方式挂载/system目录,因此,非root手机用户是无法删除这些app的. 如果我们已经成功获取了手机的root权限,就可以通过下面的方法直接删除掉系统出厂的app应用,假设某app的安装文件叫做x

【读书笔记-《Android游戏编程之从零开始》】6.Android 游戏开发常用的系统控件(TabHost、ListView)

3.9 TabSpec与TabHost TabHost类官方文档地址:http://developer.android.com/reference/android/widget/TabHost.html Android 实现tab视图有2种方法,一种是在布局页面中定义<tabhost>标签,另一种就是继承tabactivity.但是我比较喜欢第二种方式,应为如果页面比较复杂的话你的XML文件会写得比较庞大,用第二种方式XML页面相对要简洁得多. <?xml version="1