首先 ,Linux 系统启动的最后一步将读取init.rc这个文件,这个文件我们一般的android手机,Linux内核就是通过这个文件来启动我们的android内核的。
init.rc路径: 根目录下就有
init.rc会启动一个服务,
启动服务的语法如下
Services
services 是一些由init 启动 和 重新(如果有需要)启动的程序,当然这些程序如果是存在的。
services 的格式如下:
service <name> <pathname> [ <argument> ]*
<option>
<option>
...-------------------------------------------------------------------------------
service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
启动一个名为zygote的虚拟机程序Dalvik,位置在system/bin/app_process下,
先来说下几个概念 Dalvik.
在android源码中有几个地方是有涉及到这个,分别是
1.dalvik/dalvikvm
2.dalvik/dvz
3.frameworks/base/cmds/app_process
区别在于dalvikvm是可以用来执行java,它会创建一个虚拟机来执行JAR文件,但这个JAR文件是android用dx工具处理成dex格式的文件。
dvz是已经预装了Framework大部分类和资源的,所以他可以直接用来运行Android的类。
以上2个可能就是个测试工具,真正用到的是第3个
工作流程都是通过JNi传入类的地址和名称,然后FindClass,调用静态方法Main函数,注意,dvz也是调用静态方法Main,而不是create.我们Activity的create方法是Android framework调用的。
第3个就是我们关键的app_process
app_process与上面不同的是,它需要适配framework.
framework在启动时需要加载2个类,分别是ZygoteInit和SystemService这2个类,所以需要用到app_process. 我们来看下具体代码。
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}以上代码是在app_process的app_main.cpp里的main函数里的,启动app_process会执行到,如何启动呢?
看上面init.rc的参数,
service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server
启动服务 名称 路径 虚拟机启动的参数 服务路径 是否需要启动Zygoteinit 是否需要启动 systemservice
然后来看那个
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
这个代码也是会通过classname加载ZygoteInit的main函数,然后main函数又去做了一系列的动作,
public static void main(String argv[]) {
try {
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket(); //注册一个,启动socket服务端
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preloadClasses(); //加载framework jar
//cacheRegisterMaps();
preloadResources(); //加载系统资源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("true")) {
startSystemServer(); //启动systemservice进程,这个是zygote孵化出的第一个进程,采用fork机制
} else if (!argv[1].equals("false")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode(); 开启select机制监听文件标示符。
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
他的 main方法主要做3件事,
一 : 启动服务端socket 口,linux的select 机制,服务器端sokect是通过 Zygoteconnection的runonce来处理来自客户端Socket的各种请求,理论上,可以有多个客户端socket口,但必须只有一个服务器端Socket口。
接受到客户端指令后,就去fork一个新的进程。这样就启动了我们的客户端了哦,
二:有了服务器端口,我们还必须要有资源和必要的class文件,
关于fork,他其实就是拷贝了一份当前的进程,除了进程ID不一样,其他包括共享内存都一样,为什么要fork呢,因为他们共享了以大堆framework自带的资源和JAVA文件
fork 过程调用的都是Linux 内核层,所以可能是父进程和子进程 ,fork有返回值,返回pid =0 表示子进程,返回大于0则是父进程,
如果是子进程的话,我们还需要做一步操作,就是关闭服务器端的socket,因为我们只需要一个卵进程来孵化新进程,而不是子孵化子。
于是我们定位到了 zygoteconnection里的runonce方法,这个是select文件标示符返回正确时执行得。
try {
parsedArgs = new Arguments(args);
applyUidSecurityPolicy(parsedArgs, peer);
applyDebuggerSecurityPolicy(parsedArgs);
applyRlimitSecurityPolicy(parsedArgs, peer);
applyCapabilitiesSecurityPolicy(parsedArgs, peer);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
} catch (IllegalArgumentException ex) {
logAndPrintError (newStderr, "Invalid zygote arguments", ex);
pid = -1;
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
pid = -1;
}
if (pid == 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr); //需要关闭服务端端口。
// should never happen
return true;
} else { /* pid != 0 */
// in parent...pid of < 0 means failure
return handleParentProc(pid, descriptors, parsedArgs);
}
三 启动systemservice 创建我们的客户端。
有了服务器端,没人去调用,怎么去孵化新进程呢,在一切准备完毕后,ZygoteInit的Main函数里会调用startSystemService来启动
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
/*
* Enable debugging of the system process if *either* the command line flags
* indicate it should be debuggable or the ro.debuggable system property
* is set to "1"
*/
int debugFlags = parsedArgs.debugFlags;
if ("1".equals(SystemProperties.get("ro.debuggable")))
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
代码如下,根据args数组,启动了
com.android.server.SystemServer 类的main函数。
SystemServer是Android系统的神经中枢,我们需要利用到Android系统的大部分功能都在该进程中进行。Ams,Wms,Pms都是以线程在这个进程中运行的,他们一起协同工作。
SystemServer的Main方法会调用一个init1(),然后会回调本类的init2(),在该方法里启动了一个ServerThread对象,里面的run方法启动了很多的服务,而且启动的方式都不同,我们主要关注AMS的启动和一些初始化。
接下来我们来看下AMS 的用处,比较关键,
















