Android内核开发 学习笔记

前言
本文是通过学习了卢俊系列博客做的一篇学习记录文章。记录个人觉得比较有用的部分内容,该系列博文主要讲解了Android系统的开机过程和优化的分析处理。最近也在处理开机优化的问题,特此记录之。

Android内核开发:序
Android内核开发:开发板选购
Android内核开发:理解和掌握repo工具
下载manifest仓库
repo init -u https://android.googlesource.com/platform/manifest 
如果要选择特定版本的Android源码,或者在已下载的源码基础上切换到其他版本,则可以使用-b选项: 
repo init -u git://git.omapzoom.org/platform/manifest.git -b android-5.0.2_r1 
然后使用repo sync同步代码 
repo sync

mainfest.xml文件清单
上面提到了repo init需要初始化一个manifest仓库,仓库中含有一个很重要的manifest.xml文件清单,其实这个manifest.xml并不复杂的,它就是用XML文件的格式记录了本项目依赖的各个Git仓库的名称、地址,以及分支等信息。常用的元素如下所示:

manifest 最顶层的XML元素
remote 设置远程git服务器的属性,如名称、根URL地址等
project 需要clone的Git仓库,path表示本机路径,name表示远程版本库的相对路径
copyfile 执行拷贝操作,把URL/src地址的文件拷贝到./src地址的文件拷贝到./dest
repo几个常用的命令
repo init // 初始化repo仓库
repo sync // 下载源码
repo start // 创建分支
repo checkout //切换分支
repo branches //查看分支
repo status //查看文件状态
Android内核开发:源码的版本与分支详解
查看android源码分支和版本

git –git-dir .repo/manifests/.git/ branch -a

或者

cd .repo/manifests 
git branch -a | cut -d / -f 3

如果要切换的其他分支,执行下面的命令即可

repo init -b android-4.2.2_r1 
repo sync

Android内核开发:系统编译输出的镜像文件
Android内核开发:系统分区与镜像文件的烧写
Android内核开发:图解Android系统的启动过程
主要分析下init程序,它是分析Android启动过程中最核心的程序。 
代码路径:system/core/init/init.c 
init程序最核心的工作主要有3点: 
1. 创建和挂载一些系统目录/设备节点,设置权限,如:/dev, /proc, and /sys 
2. 解析 init.rc 和 init.hardware.rc,并启动属性服务,以及一系列的服务和进程。 
3. 显示boot logo,默认是“Android”字样

最重要的是第二步,这个过程中会启动系统所需功能的各种服务。主要分为本地服务和Android服务,它们都会在ServiceManager中进行注册。

本地服务 
本地服务是指运行在C++层的系统守护进程,一部分有init进程直接启动,它们定义在init.rc脚本中,还有一部分本地服务是由这些本地服务启动,如果mediaserver服务会启动AudioFlinger,MediaPlayerService,以及CameraService等本地服务。 
每一个由init直接启动的本地服务都是一个独立的Linux进程,可以通过adb shell top查看相应的进程。
Android服务 
Android服务是指运行在Dalvik虚拟机进程中的服务。 
init进程会执行app_process程序,创建Zygote进程,它是Android系统最重要的进程,后续所有的Android应用程序都是由它fork出来的。 
Zygote进程会先fork出SystemServer进程,SystemServer进程就会启动所有的Android核心服务。例如:Activity Manager、Window Manager、Power Manager等等服务。当所服务启动完毕后,SystemServer会打印出”Making services ready”,然后通过Activity Manager启动Home界面,并发送“ACTION_BOOT_COMPLETED”广播消息。 
SystemServer进程添加的服务都属于SystemServer进程。
下图为Android系统启动过程: 


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

Android是基于Linux内核的系统,因此Android的启动过程是分为两个阶段的,第一个阶段就是Linux内核的启动,第二个阶段就是Android框架的启动(包括核心服务和程序)。

Android的log系统是独立于Linux内核的log系统的。Linux内核通过printk打印的log信息,这些log写入到了/dev/kmsg文件中,在Shell终端可以通过dmesg命令查看这些log信息。Android框架则是通过Logger驱动打印log信息,这些log并没有归并到kmesg文件中,而是单独存储的,位于/dev/log目录下,在Shell终端可以通过logcat命令来查看。

通过dmesg命令抓取Linux内核的log信息

adb shell dmesg > D:\dmesg.txt

Android系统把Log分为了四类,不同的类别记录不同的Log信息:

main - 主要的Log信息,大部分应用级别的Log信息都在这里 
events - 系统事件相关的Log信息 
radio - 无线/电话相关的Log信息 
system - 低级别的系统调试Log信息

logcat默认抓取的是main信息,如果想抓取指定类别的log信息的方法,在logcat命令后加-b参数,例如:

$ adb logcat -d -v time -b "main"   >  D:\main.txt
$ adb logcat -d -v time -b "events" >  D:\events.txt
$ adb logcat -d -v time -b "system" >  D:\system.txt
$ adb logcat -d -v time -b "radio"  >  D:\radio.txt
1
2
3
4
查看系统启动时间

adb logcat -d -b events | grep “boot”

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


通过dmesg抓取log信息

adb shell dmesg > D:\dmesg.txt

在dmesg.txt中搜索几个关键字 
Zygote、system_server、mediaserver等关键字可以获取相关模块的开机耗时信息。

Android内核开发:系统启动速度优化
Android系统的启动优化主要分为三大部分: 
1. Bootloader优化 
2. Linux Kernel的剪裁与优化 
3. Android OS部分的剪裁与优化

下面主要讲Android os部分的优化 
1. 精简preload的classes和resource 
frameworks/base/preload-classes 
frameworks/base/core/res/res/values/arrays.xml 
2. 精简native service和java service 
system/core/rootdir/init.rc 
frameworks/base/services/java/com/android/server/SystemServer.java 
3. 精简预装的apk文件 
build/target/product/xxxx.mk 
device///xxxx.mk 
vendor/…./xxxx.mk 
4. 减少内核的log打印级别 
system/core/rootdir/init.rc 
5. 其他优化手段 
- 优化启动动画,降低帧率和图片尺寸 
- 精简系统,减小boot.img文件大小,可以显著减少启动过程中加载和解压boot.img的时间 
- 预先创建一些目录和文件,而不是在init过程中创建

Android内核开发:浅析APK的安装过程
Android内核开发:从源码树中删除出厂的app应用
Android内核开发:在源码树中添加新的app应用
不带jni本地代码
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := HelloWorld
include $(BUILD_PACKAGE)
1
2
3
4
5
6
含有jni本地代码
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := HelloWorld
LOCAL_JNI_SHARED_LIBRARIES := libmynative
include $(BUILD_PACKAGE)

include $(call all-makefiles-under,$(LOCAL_PATH))
1
2
3
4
5
6
7
8
9
10
11
JNI目录下的Android.mk文件(假设jni目录下有inc和src目录)

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libmynative
LOCAL_SRC_FILES := src/mynative.c
LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc

include $(BUILD_SHARED_LIBRARY)
1
2
3
4
5
6
7
8
9
含有jni本地代码,并且本地代码依赖第三方库(.a或者so) 
假设本地代码依赖的第三方库为:encoder.a 和 decoder.so

修改上述jni目录下的Android.mk

LOCAL_STATIC_LIBRARIES := libencoder
LOCAL_SHARED_LIBRARIES := libdecoder
1
2
修改HelloWorld目录下的Android.mk文件(encoder.a 和 decoder.so 都拷贝到工程根目录)

include $(CLEAR_VARS)
LOCAL_MODULE := libencoder
LOCAL_SRC_FILES := encoder.a
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_MODULE_SUFFIX := .a
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE := libdecoder
LOCAL_SRC_FILES := decoder.so
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
include $(BUILD_PREBUILT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Android内核开发:为什么刷机后系统第一次启动会很慢?
--------------------- 
作者:qqxiaoqiang1573 
来源:CSDN 
原文:https://blog.csdn.net/QQxiaoqiang1573/article/details/57086865 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/kyopeng123/article/details/85241476