Android系统启动过程详解

前言

一直想研究Android完整的启动过程,网上看了不少资料,也看了书上的一些说明,对这些观点有些怀疑,于是自己分析了系统启动的完整过程。从内核启动第一个用户程序init开始说起,直到Home应用的启动,每一步都有源代码展示。希望能解除读者对Android系统启动过程中的困惑,若有什么疑问,欢迎留言交流。本研究基于CM10.1源码,读者若能对照源代码查看效果会更好。

1) init启动servicemanager和 zygote两个service

Android底层是Linux内核,和linux类似,内核初始化后启动的第一个用户进程是init,它会解析init.rc脚本,启动init.rc里声明的service,并执行一些action。在init.rc里有启动Andriod空间的一些关键服务,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#…
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm
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
#…

servicemanager负责管理所有的binder service, 这些binder service有native的,也有java的。native的binder service有surfaceflinger,drm,media等,java的binder service就有我们平常熟悉的很多管理服务了,ActivityManagerService,WindowManagerService,BatteryService,PowerManagerService,InputManagerService等等。service manager并不负责这些binder service的创建,native的binder service大多由init启动init.rc里的service时创建并启动,java层的binder service大多由zygote创建并启动的,接下来会详细这些service是如何被启动的。

2) zygote service启动java层的ZygoteInit

zygote服务是java层所有程序进程的父进程,它是Android空间程序的孵化器,Android空间所有程序都是由zygote进程启动的。zygote service对应/system/bin/app_process程序,源代码位于frameworks/base/cmds/app_process/app_main.cpp,启动时的main函数代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
int main(int argc, const char* const argv[])
{
//...
/*runtime就是dalvik虚拟机实例,启动Java层应用时,
 *会fork 一个子进程,复制虚拟机,许多书上将runtime看作一个进程,
 *然后再启动zygote进程,个人觉得这是错误的 
 */		 
AppRuntime runtime;
//... 
while (i < argc) {
    const char* arg = argv[i++];
    if (!parentDir) {
        parentDir = arg;
  /*init.rc启动app_main会设置参数--zygote*/ 
    } else if (strcmp(arg, "--zygote") == 0) {
        zygote = true;
        niceName = "zygote"; //进程的名字
  /*init.rc启动app_main会设置参数--start-system-server,
   *表示需启动systemserver
   */
    } else if (strcmp(arg, "--start-system-server") == 0) {
        startSystemServer = true;
 /*启动应用时会使用--application参数*/             
    } else if (strcmp(arg, "--application") == 0) {
        application = true;
/*--nice-name=参数表示要设置的进程名字*/            
    } else if (strncmp(arg, "--nice-name=", 12) == 0) {
        niceName = arg + 12;
    } else {
        className = arg;
        break;
    }
}    
/*设置进程名*/
if (niceName && *niceName) {
    setArgv0(argv0, niceName);
    set_process_name(niceName);
}
/*设置虚拟机运行环境的父目录*/
runtime.mParentDir = parentDir;
if (zygote) {
/*虚拟机里启动com.android.internal.os.ZygoteInit,
 *并传递参数start-system-server
 */
    runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer ? "start-system-server" : "");
} else if (className) {        
    /*若不是zygote,则启动的第一个类是com.android.internal.os.RuntimeInit,
     *RumtimeInit初始化后会启动mClassName
     */
    runtime.mClassName = className;
    runtime.mArgC = argc - i;
    runtime.mArgV = argv + i;
    runtime.start("com.android.internal.os.RuntimeInit",
            application ? "application" : "tool");
} 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;
}
//...
}

通过上述代码可知道zygote service将运行dalvik虚拟机,并在虚拟机里执行com.android.internal.os.ZygoteInit,还给它传递了参数start-system-server

3) ZygoteInit启动SystemServer

ZygoteInit启动时的相关源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void main(String argv[]) {
{
try {   
   //...
   //在某个描述符上监听连接请求,
   //其它Android空间的程序的启动都是通过连接zygote才孵化出来的
   registerZygoteSocket();
   //... 
   if (argv[1].equals("start-system-server")) {
        //启动SystemServer
        startSystemServer();
    } else if (!argv[1].equals("")) {
        throw new RuntimeException(argv[0] + USAGE_STRING);
    }
   //...
   /*ZYGOTE_FORK_MODE默认为false,如果为true的话,每收到一个连接请求,
    *就会建立一个新进程,然后再运行连接请求所要求执行的命令,此时会建立另一个新进程
    */
    if (ZYGOTE_FORK_MODE) {
        runForkMode();
    } else {
       //使用Select poll的方式来建立新进程,收到连接请求后,也会建立进程启动某个程序
        runSelectLoopMode();
    }
 
    closeServerSocket();
} catch (MethodAndArgsCaller caller) {
    caller.run();
} catch (RuntimeException ex) {
    Log.e(TAG, "Zygote died with exception", ex);
    closeServerSocket();
    throw ex;
}
}

从上述代码可知道会调用startSystemServer以启动SystemServer,相关源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
private static boolean startSystemServer()
{
/* Hardcoded command line to start the system server */
//启动SystemServer使用的参数
String args[] = {
    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,3001,3002,3003,3004,3006,3007,3009",
    "--capabilities=130104352,130104352",
    "--runtime-init",
    "--nice-name=system_server",
    //注意:就是在这里设置要启动的SystemServer包名及类名,故此后续才能启动SystemServer
    "com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
    /*将args参数传给ZygoteConnection进行转化,--形式的参数将全部被接收
     * 但是要启动的类的类名com.android.server.SystemServer会放在
     *ZygoteConnection.Arguments的remainingArgs里,后来调用handleSystemServerProcess时会用到
     */
    parsedArgs = new ZygoteConnection.Arguments(args); 
    /*添加额外运行参数*/
    ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); 
    /*开启新进程*/
    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) {
	  /*调用handleSystemServerProcess会执行ZygoteConnection.Arguments的remainingArgs参数
	   *所指定的类,即com.android.server.SystemServer	   
	   */
    handleSystemServerProcess(parsedArgs);
}
}

ZygoteInit的startSystemServer会调用forkSystemServer,然后:

ZygoteInit.forkSystemServer -> Zygote.nativeForkSystemServer-> dalvik_system_Zygote.cpp 里的Dalvik_dalvik_system_Zygote_forkSystemServer-> forkAndSpecializeCommon->fork建立新进程

ZygoteInit的startSystemServer会调用handleSystemServerProcess来真正启动systemserver,相关源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
//... 
if (parsedArgs.niceName != null) {
    Process.setArgV0(parsedArgs.niceName);
}
//启动systemserver时invokeWith为null
if (parsedArgs.invokeWith != null) {
    WrapperInit.execApplication(parsedArgs.invokeWith,
            parsedArgs.niceName, parsedArgs.targetSdkVersion,
            null, parsedArgs.remainingArgs);
} else {
    /*
     * 启动systemserver时,parsedArgs.remainingArgs为com.android.server.SystemServer.
     */
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}

然后的流程是

RuntimeInit.zygoteInit-> applicationInit,applicationInit的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void applicationInit(int targetSdkVersion, String[] argv)
{
//...
final Arguments args;
try {
    //参数转换,系统启动时,argv里有一个参数是com.android.server.SystemServer
    args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
    Slog.e(TAG, ex.getMessage());
    // let the process exit
    return;
}
//...
//终于在此启动了SystemServer
invokeStaticMain(args.startClass, args.startArgs)
}

4) SystemServer 启动过程

执行com.android.server.SystemServer时,main函数里会调用init1函数,init1函数是一个本地函数,init1的实现放在frameworks/base/services/jni/com_android_server_SystemServer.cpp里,对应的jni函数是android_server_SystemServer_init1,在该函数里会调用system_init,而system_init的实现是在frameworks/base/cmds/system_server/library/system_init.cpp,该函数的实现代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
extern "C" status_t system_init()
{
//... 
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p\n", sm.get());
sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
    // Start the SurfaceFlinger
    SurfaceFlinger::instantiate();
}
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
    // Start the sensor service
    SensorService::instantiate();
}
// And now start the Android runtime.  We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
ALOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
ALOGI("System server: starting Android services.\n");
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
    return UNKNOWN_ERROR;
}
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
    return UNKNOWN_ERROR;
}
//反过来调用Java里SystemServer的init2函数
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
    return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
ALOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("System server: exiting thread pool.\n");
}

5) 启动Java层的各种binder service

调用SystemServer的init2函数后,会开启新线程android.server.ServerThread,在新线程里会启动各种Java层的binder service,并在service manager里注册,这些Service大多开启了新线程运行,故此都是systemserver的子线程,添加的Service列表如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
ServiceManager.addService("entropy", new EntropyMixer());
ServiceManager.addService(Context.POWER_SERVICE, power);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
ServiceManager.addService("telephony.registry", telephonyRegistry);
ServiceManager.addService(Context.SCHEDUL
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的服务(Service)是一种长时间运行在后台的组件,而onStartCommand方法则是服务的生命周期中最重要的一个方法,它会在服务启动时被调用。在服务的启动过程中,我们可以通过在onStartCommand方法中编写一些保活代码来保证服务不被系统杀死,从而达到保活的效果。 下面是一个简单的保活代码示例: ```java public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } } ``` 在这段代码中,我们重写了Service的onStartCommand方法,并返回了START_STICKY常量。START_STICKY表示服务被杀死后会自动重启,并且会尝试重新创建Intent对象并调用onStartCommand方法,从而达到保活的效果。 但是,仅仅返回START_STICKY是不够的,我们还需要在服务中进行一些操作,从而让系统认为服务是正在运行的。下面是一个完整的保活代码示例: ```java public class MyService extends Service { private static final String TAG = "MyService"; private static final int SERVICE_ID = 1001; private static final String CHANNEL_ID = "MyService channel"; private static final String CHANNEL_NAME = "MyService"; private NotificationManager mNotificationManager; @Override public void onCreate() { super.onCreate(); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); createNotificationChannel(); startForeground(SERVICE_ID, createNotification()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); return START_STICKY; } private Notification createNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle(getString(R.string.notification_title)) .setContentText(getString(R.string.notification_content)) .setSmallIcon(R.mipmap.ic_launcher); return builder.build(); } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW); mNotificationManager.createNotificationChannel(channel); } } } ``` 在这个代码示例中,我们在服务的onCreate方法中创建了一个通知栏通知,并通过调用startForeground方法将服务设置为前台服务。这样,即使应用被切到后台,服务也会一直在运行并且不会被系统杀死。 需要注意的是,Android 8.0及以上版本要求通知栏通知必须设置通知渠道才能正常显示,因此我们在createNotificationChannel方法中创建了一个通知渠道。 调用这段代码的过程如下: 1. 在AndroidManifest.xml中声明MyService服务: ```xml <service android:name=".MyService" android:enabled="true" android:exported="false" /> ``` 2. 在需要启动服务的地方调用startService方法: ```java Intent intent = new Intent(this, MyService.class); startService(intent); ``` 3. 当服务启动后,会在logcat中输出"onStartCommand",并在通知栏中显示通知。 这就是一个简单的Android onStartCommand保活代码的详解,并调用代码全过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值