前言
一直想研究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