*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
解读Android的源码可以让我们更好的学习系统的优秀源码,以及google工程师对于一个程序的是如何实现的,从源码的分析也可以强化我们的编程思想.
Android系统启动流程源码分析,基于Android5.1(个人比较喜欢这个版本的源码,因为改动比较大)
Android系统是基于linux内核的,所以在Android启动的时候会先去加载linux内核,内核启动的时候会去加载各种驱动以及数据结构等,然而,Android的第一个进程是初始化进程(init).
进程是由C代码实现的,即init.c;所以我们先从init.c开始阅读.由于init.c文件在Android源码中是有很多个的,我们需要阅读的是内核core的init文件,注意包名不要错误.
在C语言中,main方法是函数的入口,我们先从main函数开始;由于是分析代码,所以我会把不需要的部分的代码删除,仅留下部分作为例子
int main(int argc, char **argv)
{
//step1 创建必要的文件夹 , 权限分配 7代表可读可写可执行 5代表可读可执行不可写 挂载磁盘
mkdir("/dev", 0755);
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
//step2 初始化代码 包括日志初始化 配置文件初始化 以及硬件层初始化
klog_init();
property_init();
//setp3 需要注意的一个初始化是init.rc配置文件的初始化 此处插入init.rc解读 详细请跳转 2.init.rc解读
init_parse_config_file("/init.rc");
//setp4 后续是很多的队列等待,等待初始化的完成,以及一些初始化失败的操作代码
action_for_each_trigger("early-init", action_add_queue_tail);
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
return 0;
}
mkdir /sys/fs/cgroup/memory 0750 root system
mount cgroup none /sys/fs/cgroup/memory memory
write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
chown system system /sys/kernel/ipv4/tcp_rmem_max
setp2 服务的启动,如下实例是一个大家比较熟悉的服务,网络模块服务启动,此项初始化了socket的网络通信
Daemon processes to be run by init.
service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet
setp3 重点服务讲解,孵化器服务
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote //重点注意代码
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
服务器服务zygote,进程的出现都是有孵化器完成的,也就是说孵化器进程是母进程
但是比较奇怪的是并没有在这个文件中出现直接启动的服务器进程的服务呢?这个就比较麻烦啦 哈哈
好好想一下,文件中既然有提到,onrestart restart zygote,从java的思想出发的话,这个文件里面一定是导入了服务器进程的包的,那么我们看一下文件的关联文件有哪些吧
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.${ro.zygote}.rc
import /init.trace.rc
在文件的顶头会发现有一个import /init.${ro.zygote}.rc的文件关联,那么去找一下这个文件吧,搜索这个文件会发现有好几个,因为操作系统的位数分为了四个,但是其中内容都是一样的,细微差距就是app_process的路径文件夹名字会不一样,不过都指向同一个路径
如下:
//service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
**setp4 在这个服务中,可以看到路径是在app_process,看一下这个路径中的文件,只有一个文件**App_main.cpp,这个C++文件就是孵化器进程了
这次是一个C++文件,C++和C语言一样,入口函数都是main函数
int main(int argc, char* const argv[])
{
//step1 忽略一些参数初始化方法
//step2 AppRuntime为Android的运行时对象,下面代码是初始化了一个Android运行时环境
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
//step3 初始化一些重要参数,后续对参数判断,参数初始化的时候会跳过第一个参数及父级路径
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
//step4 现在开始启动android的代码,com.android.internal.os.ZygoteInit
//看到这样的是不是很熟悉啦,此类为android的孵化器进程
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
step1 package com.android.internal.os;此类所在包
step2 对于java代码而言就没有什么main函数了,我们要从构造方法开始看
/**
* Class not instantiable.
* 比较尴尬 不给调用
*/
private ZygoteInit() {
}
孵化器的类是一个私有的构造方法,是不允许我们直接实例的类,那么按照常规的java代码套路的话,一般是有一个静态方法去创建他或者直接获得一个实例的,
但是找了一下,居然没有,哈哈!但很是意外的发现有一个main方法:
step3 main方法解读
public static void main(String argv[]) {
//在2.3的android\源码中是有一个运行时设置堆内存大小的,不过貌似被取消了
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
/*
*值得提醒一下的是,google的工程师在写代码的时候会有很多的逻辑判断
*系统级别的程序代码就是严谨
*/
//孵化器的socket注册
registerZygoteSocket(socketName);
/**
*static void preload()
*从命名可以看出这个方法是用作预加载的
*预加载中内容比较多,也比较重要,下面会详细介绍
*跳转 5.预加载preload();
*/
preload();
// Do an initial gc to clean up after startup
//需要强调的一点是,java的回收机制虽然不是你乎他他就会来的
//但是可以看到系统在做大量的IO操作的前后都会主动地去呼叫gc,可以借鉴为一个习惯
gc();
//重点启动服务
if (startSystemServer) {
//跳转 6.启动Android系统服务介绍
startSystemServer(abiList, socketName);
}
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
}
}
step1 方法内容
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses();
preloadResources();
preloadOpenGL();
preloadSharedLibraries();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
Log.d(TAG, "end preload");
}
step2 preloadClasses()预加载类说明
/**
*从配置文件PRELOADED_CLASSES = “/system/etc/preloaded-classes”读取需要加载的类
*标准的JAVA的IO读取操作
*每次读取一行,读取到后进行反射加载类
*删掉大部分代码.留下核心部分
*在android5.1中这个配置文件是有3010行
*/
private static void preloadClasses() {
is = new FileInputStream(PRELOADED_CLASSES);
try {
BufferedReader br
= new BufferedReader(new InputStreamReader(is), 256);
while ((line = br.readLine()) != null) {
try {
Class.forName(line);
} catch (ClassNotFoundException e) {
} catch (UnsatisfiedLinkError e) {
} catch (Throwable t) {
}
}
} catch (IOException e) {
} finally {
//加载
runtime.preloadDexCaches();
}
}
step3 preloadResources()加载资源,这个方法比较简单没什么好说的
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting();
try {
System.gc();
runtime.runFinalizationSync();
mResources = Resources.getSystem();
mResources.startPreloading();
//load资源数据
mResources.finishPreloading();
} catch (RuntimeException e) {
Log.w(TAG, "Failure preloading resources", e);
} finally {
Debug.stopAllocCounting();
}
}
step4 preloadOpenGL()方法,加载opengl相关,opengl是一个开源组织维护的,加载的话确实就是和java依赖库一样简单,没什么好解释的
private static void preloadOpenGL() {
if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
}
}
step5 preloadSharedLibraries()加载依赖库
private static void preloadSharedLibraries() {
Log.i(TAG, "Preloading shared libraries...");
System.loadLibrary("android");
System.loadLibrary("compiler_rt");
System.loadLibrary("jnigraphics");
}
step6 WebViewFactory.prepareWebViewInZygote()浏览器作为APP中一个比较特殊的应用.这里就不详解
public static void prepareWebViewInZygote() {
try {
//加载浏览器内核
System.loadLibrary("webviewchromium_loader");
long addressSpaceToReserve =
SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
} catch (Throwable t) {
}
}
step1 方法声明
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
//初始化参数的代码(太多,不贴代码了)
/**
* "com.android.server.SystemServer"
*参数初始化的时候有一个比较抢眼的参数SystemServer
*/
try {
/**
*args参数中封装了"com.android.server.SystemServer"这个参数
*/
parsedArgs = new ZygoteConnection.Arguments(args);
/* Request to fork the system server process */
//这个方法中可以看到fork\出了一个系统进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
//在系统进程完成之后处理剩下的一些子进程
handleSystemServerProcess(parsedArgs);
}
return true;
}
public final class SystemServer//此类被声明了为一个最终类,不可改变,公开访问
public SystemServer() {
// Check for factory test mode.//只是做了模式检测
mFactoryTestMode = FactoryTest.getMode();
}
在Android2.3的源码中,SystemServer类还包含了两个内部类,但是在5.1的版本中已经把两个内部类合并了(SensorService.cpp中),有兴趣的可以追溯一下2.3的源码
step2 main方法分析
public static void main(String[] args) {
new SystemServer().run();
//在main方法中只是调用了构造方法和run方法
}
step3 run方法分析
private void run() {
//时间初始化
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
//looper的初始化,handler处理的时候不需要自己初始化一个looper就是因为系统已经为主线程准备了looper
Looper.prepareMainLooper();
// Initialize native services
/**
*加载了一个so库文件,然后调用了init的jni方法
*libandroid_servers.so
*可以在目录中找到这个文件的so库阅读init方法
*/
System.loadLibrary("android_servers");
nativeInit();
// Start services.重点放到 第九点说明
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// Loop forever.
//到此处说明已经开始轮训去做消息处理了 完成
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
step1 源代码查找
路径:F:\Android5\android5.1\frameworks\base\services\core\jni
step2 nativeInit方法
static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
}
该方法主要调用了SensorService::instantiate(),实例了SensorService对象
step3 SensorService阅读
路径如下:F:\Android5\android5.1\frameworks\native\services\sensorservice
因为SensorService启动后执行的就是onFirstRef方法,所以我们直接看这个方法
void SensorService::onFirstRef()
{
//硬件的初始化
SensorDevice& dev(SensorDevice::getInstance());
//looper的初始化
mLooper = new Looper(false);
//运行SensorService
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
step1 硬件完成后
startBootstrapServices();
startCoreServices();
startOtherServices();
step2 startBootstrapServices()
private void startBootstrapServices() {
Installer installer = mSystemServiceManager.startService(Installer.class);
// Activity manager runs the show.Activity相关启动
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
//电源相关启动
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
mActivityManagerService.initPowerManagement();
//显示相关启动
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//应用管理器
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
//服务管理器
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
// Initialize attribute cache used to cache resources from packages.
AttributeCache.init(mSystemContext);
// Set up the Application instance for the system process and get started.
mActivityManagerService.setSystemProcess();
}
step3 startCoreServices();
这一段google工程师注释很详细了就不多解释了
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);
// Tracks the battery level. Requires LightService.
mSystemServiceManager.startService(BatteryService.class);
// Tracks application usage stats.
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// Update after UsageStatsService is available, needed before performBootDexOpt.
mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
}
step4 startOtherServices();
此处代码量非常大,认真慢慢来
private void startOtherServices() {
//前面变量初始化就删掉啦,下面代码也一样,留下重要部分
try {
//功能性服务初始化
//电话功能 此try内大部分为相似,值得注意的是,在这部分在会掉过蓝牙服务
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
} catch (RuntimeException e) {
}
//此处基本上为手机对于我们可见部分的服务启动,比如UI
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
//系统设置服务初始化,比如wifi什么的,通知什么的
mSystemServiceManager.startService("com.android.server.wifi.RttService");
//launcher服务
mSystemServiceManager.startService(LauncherAppsService.class);
}
//必要的系统配置
Configuration config = wm.computeNewConfiguration();
//可授权第三方的APP启动了,值得注意的是ActivityManagerService的systemReady()方法
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
Slog.i(TAG, "WebViewFactory preparation");
WebViewFactory.prepareWebViewInSystemServer();
//此处忽略各种判断捕获
}
});
}
路径依然还是frameworks下
step1 systemReady()方法
public void systemReady(final Runnable goingCallback) {
//在这个方法中会发现很多代码都有synchronized在修饰
synchronized(this) {
if (mSystemReady) {
// If we're done calling all the receivers, run the next "boot phase" passed in
// by the SystemServer
if (goingCallback != null) {
goingCallback.run();
}
return;
}
//安全检查,就是锁屏输密码
updateCurrentProfileIdsLocked();
if (!mDidUpdate) {
if (mWaitingUpdate) {
return;
}
final ArrayList doneReceivers = new ArrayList();
mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
public void run() {
//记载各种组件
systemReady(goingCallback);
}
}, doneReceivers, UserHandle.USER_OWNER);
}
mAppOpsService.systemReady();
mSystemReady = true;
}
//到这里的时候 系统已经万全准备好了
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
SystemClock.uptimeMillis());
//锁定栈顶的activity,至此,已经是到了手机解锁的界面了
mStackSupervisor.resumeTopActivitiesLocked();
sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
}
}
对于Android的启动源码呢,涉及到了很多的东西,方方面面,我可能讲的不是很到位,还是各位慢慢吸收理解.多多支持.