init进程
从启动电源到init
-
启动电源以及系统启动:
- 当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
-
引导程序Bootloader
- 引导程序是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
-
linux内核启动
- 内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。
- 当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。
-
init进程启动
- 创建一些文件夹并挂载设备
- 初始化和启动属性服务
- 解析init.rc配置文件并启动zygote进程
-
前面几步过于底层,下面我们主要看看真正涉及到Android系统的init进程
init入口函数
- system/core/init/init.cpp
- 入口函数为main
- 初始化属性相关资源: property_init();
- 启动属性服务: start_property_service();
- 解析init.rc配置文件: parser.ParseConfig("/init.rc");
init.rc
- system/core/rootdir/init.rc
- init.rc是一个配置文件,内部由Android初始化语言(Android Init Language)编写的脚本;
- 主要包含五种类型语句:Action、Commands、Services、Options和Import。
- 在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。我们要分析的zygote服务的启动脚本则在init.zygoteXX.rc中定义,这里拿64位处理器为例system/core/rootdir/init.zygote64.rc;
//其中service用于通知init进程创建名zygote的进程,这个zygote进程执行程序的路径为/system/bin/app_process64,后面的则是要传给app_process64的参数。class main指的是zygote的class name为main
service zygote /system/bin/app_process64 -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 audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
解析service
- system/core/init/service.cpp
- 两个主要函数:
- ParseSection函数: 解析service的rc文件,比如上文讲到的init.zygote64.rc,主要用来搭建service的架子。
- ParseLineSection函数用于解析子项。
init启动zygote
- system/core/rootdir/init.rc
- init启动zygote时主要是调用app_main.cpp的main函数中的AppRuntime的start函数来启动zygote进程;
on nonencrypted
# A/B update verifier that marks a successful boot.
exec - root -- /system/bin/update_verifier nonencrypted
class_start main
class_start late_start
//之前提到zygote的class name为main,因此class_start main用来启动zygote
属性服务
- 类似Windows平台的注册表管理器
- system/core/init/init.cpp中和属性服务相关的代码有:
property_init();
start_property_service();
//初始化属性服务配置并启动属性服务
Zygote进程
Zygote简介
- 也称为孵化器,创建了DVM(Dalvik虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程;
- 由于Zygote进程在启动时会创建DVM,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。
- 主要步骤:
- 创建AppRuntime并调用其start方法,启动Zygote进程。
- 创建DVM并为DVM注册JNI.
- 通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
- 通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。
- 启动SystemServer进程。
- 入口:frameworks/base/cmds/app_process/app_main.cpp的main函数
int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
Vector<String8> args;
if (!className.isEmpty()) {
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));//1
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//2
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} 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;
}
}
- 注释1处如果startSystemServer为true的话(默认为true),将”start-system-server”放入启动的参数args。
- 注释2处这里调用runtime的start函数来启动zygote进程,并将args传入,这样启动zygote进程后,zygote进程会将SystemServer进程启动。我们知道runtime指的就是AppRuntime,AppRuntime声明也在app_main.cpp中,它继承AndroidRuntime,也就是我们调用start其实是调用AndroidRuntime的start函数:
- frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {//1
return;
}
onVmCreated(env);
if (startReg(env) < 0) {//2
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
//创建数组
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
//从app_main的main函数得知className为com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit的main函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");//3
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//通过JNI调用ZygoteInit的main函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);//4
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
...
}
- 注释1处调用startVm函数来创建JavaVm(DVM)
- 注释2处调用startReg函数用来为DVM注册JNI。
- 注释3处的代码用来找到ZygoteInit的main函数,其中startClass从app_main的main函数得知为com.android.internal.os.ZygoteInit。
- 注释4处通过JNI调用ZygoteInit的main函数,因为ZygoteInit的main函数是Java编写的,因此需要通过JNI调用。
Zygote的Java框架层
- 上文我们通过JNI调用ZygoteInit的main函数后,Zygote便进入了Java框架层,此前没有任何代码进入过Java框架层,换句话说Zygote开创了Java框架层。
- frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
try {
...
//注册Zygote用的Socket
registerZygoteSocket(socketName);//1
...
//预加载类和资源
preload();//2
...
if (startSystemServer) {
//启动SystemServer进程
startSystemServer(abiList, socketName);//3
}
Log.i(TAG, "Accepting command socket connections");
//等待客户端请求
runSelectLoop(abiList);//4
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
- 通过上面代码得知,ZygoteInit的main函数主要做了4件事:
- registerZygoteSocket:创建LocalServerSocket,也就是服务端的Socket,当Zygote进程将SystemServer进程启动后,就会在这个服务端的Socket上来等待ActivityManagerService请求Zygote进程来创建新的应用程序进程。
- 启动SystemServer进程:创建args数组,这个数组用来保存启动SystemServer的启动参数,将args数组封装成Arguments对象并供forkSystemServer函数调用。forkSystemServer函数通过fork函数在当前进程创建一个子进程,如果返回的pid为0,也就是表示在新创建的子进程中执行的,则执行handleSystemServerProcess来启动SystemServer进程。
- runSelectLoop: 启动SystemServer 进程后,最后进入 runSelectLoop 函数
SyetemServer进程
SyetemServer进程的启动过程
- 主要步骤:
- 1.启动Binder线程池,这样就可以与其他进程进行通信。
- 2.创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理。
- 3.启动各种系统服务。
- 上面说了ZygoteInit.java的startSystemServer函数中启动了SyetemServer进程;
- 在startSystemServer函数中调用handleSystemServerProcess来启动SyetemServer进程,代码如下
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
- handleSystemServerProcess代码:
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
//SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,
//这个Socket对于SyetemServer进程没有用处,因此,需要关闭该Socket。
...
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
//调用RuntimeInit的zygoteInit函数
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
- 上面代码调用了调用RuntimeInit的zygoteInit函数,zygoteInit函数中又调用了nativeZygoteInit函数,代码如下,其主要做的就是启动Binder线程池,这样SyetemServer进程就可以使用Binder来与其他进程进行通信了。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();//1
applicationInit(targetSdkVersion, argv, classLoader);//2
}
- 上面applicationInit函数中主要调用了invokeStaticMain函数,invokeStaticMain最终通过反射调用到SystemServer的main函数;
- frameworks/base/services/java/com/android/server/SystemServer.java的main函数如下:
public static void main(String[] args) {
new SystemServer().run();
}
- 可以看到main函数中只调用了SystemServer的run函数
private void run() {
...
//加载了libandroid_servers.so
System.loadLibrary("android_servers");
...
//创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
...
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
//startBootstrapServices函数中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。
startBootstrapServices();
//startCoreServices函数启动了BatteryService、UsageStatsService和WebViewUpdateService。
startCoreServices();
//startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService。
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
...
}
- 由上面代码可以看出官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务;
- 比如要启动PowerManagerService则会调用如下代码:
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
- SystemServiceManager的startService函数如下
public <T extends SystemService> T startService(Class<T> serviceClass) {
...
final T service;
try {
//创建入参类型的SystemService,如PowerManagerService
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
throw new RuntimeException("Failed to create service " + name
+ ": service could not be instantiated", ex);
}
...
// Register it.
//将PowerManagerService添加到mServices中,这里mServices是一个存储SystemService类型的ArrayList
mServices.add(service);//2
// Start it.
try {
//接着调用PowerManagerService的onStart函数启动PowerManagerService并返回,这样就完成了PowerManagerService启动的过程。
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + name
+ ": onStart threw an exception", ex);
}
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
- 除了用mSystemServiceManager的startService函数来启动系统服务外,也可以通过如下形式来启动系统服务,以PackageManagerService为例:
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//直接调用了PackageManagerService的main函数
Launcher进程
Launcher的启动流程
- 前面讲了init进程、Zygote进程和SyetemServer进程的启动过程,现在就来到了Android系统启动流程的最后一步,Launcher的启动流程;
- Android系统启动的最后一步是启动一个Home应用程序,这个应用程序用来显示系统中已经安装的应用程序,这个Home应用程序就叫做Launcher。
- 应用程序Launcher在启动过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。
- SyetemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的ActivityManagerService会将Launcher启动起来。
- 启动Launcher的入口为ActivityManagerService的systemReady函数,代码如下:
- frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
}
- 经过多次调用,最终会调用到startHomeActivityLocked
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {//1
return false;
}
Intent intent = getHomeIntent();//2
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {//3
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);//4
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
- 上面的getHomeIntent函数代码如下:
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
- mTopAction的值为Intent.ACTION_MAIN, 并且如果系统运行模式不是低级工厂模式则将intent的Category设置为Intent.CATEGORY_HOME。假设系统的运行模式不是低级工厂模式,则判断符合Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME的应用程序是否已经启动,如果没启动则调用mActivityStarter.startHomeActivityLocked方法启动该应用程序。
- 这个被启动的应用程序就是Launcher,因为Launcher的Manifest文件中的intent-filter标签匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。
- 这样,应用程序Launcher就会被启动起来,并执行它的onCreate函数。
Launcher中应用图标显示流程
//加载系统已经安装的应用程序信息:
private void loadAndBindAllApps() {
if (DEBUG_LOADERS) {
Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
}
if (!mAllAppsLoaded) {
loadAllApps();//1
synchronized (LoaderTask.this) {
if (mStopped) {
return;
}
}
updateIconCache();
synchronized (LoaderTask.this) {
if (mStopped) {
return;
}
mAllAppsLoaded = true;
}
} else {
onlyBindAllApps();
}
}
//如果系统没有加载已经安装的应用程序信息,则会调用注释1处的loadAllApps函数:
private void loadAllApps() {
...
mHandler.post(new Runnable() {
public void run() {
final long bindTime = SystemClock.uptimeMillis();
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindAllApplications(added);//1
if (DEBUG_LOADERS) {
Log.d(TAG, "bound " + added.size() + " apps in "
+ (SystemClock.uptimeMillis() - bindTime) + "ms");
}
} else {
Log.i(TAG, "not binding apps: no Launcher activity");
}
}
});
...
}
//callbacks.bindAllApplications这个callbacks实际是指向Launcher的
public void bindAllApplications(final ArrayList<AppInfo> apps) {
if (waitUntilResume(mBindAllApplicationsRunnable, true)) {
mTmpAppsList = apps;
return;
}
if (mAppsView != null) {
mAppsView.setApps(apps);//1
}
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
}
}
//在注释1处会调用AllAppsContainerView的setApps函数,并将包含应用信息的列表apps传进去;
//包含应用信息的列表apps已经传给了AllAppsContainerView,查看AllAppsContainerView的onFinishInflate函数:
@Override
protected void onFinishInflate() {
super.onFinishInflate();
...
// Load the all apps recycler view
mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);//1
mAppsRecyclerView.setApps(mApps);//2
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);//3
mAppsRecyclerView.setHasFixedSize(true);
mAppsRecyclerView.addOnScrollListener(mElevationController);
mAppsRecyclerView.setElevationController(mElevationController);
...
}
//onFinishInflate函数在加载完xml文件时就会调用,在注释1处得到AllAppsRecyclerView用来显示App列表,并在注释2处将apps的信息列表传进去,并在注释3处为AllAppsRecyclerView设置Adapter。这样应用程序快捷图标的列表就会显示在屏幕上。
Android系统启动流程
- 启动电源以及系统启动
- 当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
- 引导程序BootLoader
- 引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
- Linux内核启动
- 内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。
- init进程启动
- 初始化和启动属性服务,并且启动Zygote进程。
- Zygote进程启动
- 创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。
- SystemServer进程启动
- 启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
- Launcher启动
- 被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。