上兩篇聊了Launcher之后的流程褪那,現(xiàn)在咱們再看一下之前的流程 --- 也就是Zygote進(jìn)程啟動之后:
Zygote, 意為“受精卵”,安卓進(jìn)程孵化器
上圖可以看出隔嫡,由linux kernel 的 init (一生萬物)進(jìn)程可以啟動Zygote進(jìn)程,Zygote又啟動dalvik书在,初始化java環(huán)境灰伟,app需要的資源,系統(tǒng)服務(wù)... fork(孵化)桌面Launcher以及各個app進(jìn)程
在系統(tǒng)啟動腳本system/core/rootdir/init.rc文件中儒旬,我們可以看到啟動Zygote進(jìn)程的腳本命令:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666 # zygote需要一個套接字
onrestart write /sys/android_power/request_state wake # zygote重啟的話栏账,需要執(zhí)行這個操作
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
app_process對應(yīng)的源碼在frameworks/base/cmds/app_process目錄下,其入口函數(shù)main在文件app_main.cpp中:
/*
* 啟動zygote的方式為/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
* 所以 argc == 5
* argv里頭存的就是這5個參數(shù)argv[0]=="/system/bin/app_process" ,argv[1] == "-Xzygote"....
*/
int main(int argc, char* const argv[])
{
......
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
// 以上代碼主要是將參數(shù)相關(guān)信息保存到全局變量中
AppRuntime runtime;
const char* argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv); // 這個函數(shù)會返回1栈源,表示只處理了-Xzytote這一個參數(shù)挡爵,所謂的處理實(shí)際上就是將這個參數(shù)添加到了runtime對象的mOptions 變量中。
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
// 進(jìn)入循環(huán)之前 i == 1, argc == 4 argv 指向“-Xzygote”
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg; // parentDir被賦值為"/system/bin"
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote"; // 進(jìn)程名
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) { // 不走這個分支
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) { // 不走這個分支
niceName = arg + 12;
} else { // 不走這個分支
className = arg;
break;
}
}
if (niceName && *niceName) { // 設(shè)置進(jìn)程名
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) { // 走這個分支
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
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;
}
}
main函數(shù)主要就是創(chuàng)建了runtime實(shí)例甚垦,并且解析參數(shù)茶鹃,然后調(diào)用runtime的start函數(shù),接著我們分析AppRuntime的start函數(shù):
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
// 首先我們明確下傳進(jìn)來的參數(shù) className == "com.android.internal.os.ZygoteInit" options == "start-system-server"
void AndroidRuntime::start(const char* className, const char* options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (strcmp(options, "start-system-server") == 0) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1); //配置ANDROID_ROOT環(huán)境變量
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
//1:調(diào)用startVm函數(shù)創(chuàng)建虛擬機(jī)艰亮;
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) { // 創(chuàng)建虛擬機(jī)
return;
}
onVmCreated(env);
//2:調(diào)用startReg函數(shù)注冊Android Natvie函數(shù)闭翩;
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray, 1, optionsStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//3:讓虛擬機(jī)去執(zhí)行com.android.internal.os.ZygoteInit的main函數(shù)。
/* 調(diào)用com.android.internal.os.ZygoteInit的main函數(shù)垃杖,strArray是參數(shù)男杈,數(shù)組里面有兩個元素,
className == "com.android.internal.os.ZygoteInit" options == "start-system-server" */
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
start函數(shù)主要做了以下幾件事情:
1:調(diào)用startVm函數(shù)創(chuàng)建虛擬機(jī);
2:調(diào)用startReg函數(shù)注冊Android Natvie函數(shù)调俘;
3:讓虛擬機(jī)去執(zhí)行com.android.internal.os.ZygoteInit的main函數(shù)伶棒。
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
// 1、創(chuàng)建一個套接字彩库,用于監(jiān)聽ams發(fā)過來的fork請求
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
// 2肤无、加載classes 和resources, 后面會詳細(xì)分析
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("start-system-server")) {
//3、 創(chuàng)建system server進(jìn)程骇钦,ams wms pms等常見service都在該進(jìn)程里面
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
// 4宛渐、進(jìn)入循環(huán)監(jiān)聽模式,監(jiān)聽外來請求
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
com.android.internal.os.ZygoteInit的main函數(shù)主要做了四件事情:
1:調(diào)用registerZygoteSocket()創(chuàng)建一個套接字眯搭,用于監(jiān)聽ams發(fā)過來的fork請求窥翩,如下:
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
//此處的socket name,就是zygote
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//記得么鳞仙?在init.zygote.rc被加載時寇蚊,就會創(chuàng)建一個名為zygote的socket
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
//獲取zygote socket的文件描述符
fd.setInt$(fileDesc);
//將zygote socket包裝成一個server socket
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
2:調(diào)用preload()預(yù)加載classes 和resources,如下棍好;
static void preload() {
Log.d(TAG, "begin preload");
//讀取文件framework/base/preloaded-classes仗岸,然后通過反射加載對應(yīng)的類
//需要加載數(shù)千個類允耿,啟動慢的原因之一
preloadClasses();
//負(fù)載加載一些常用的系統(tǒng)資源
preloadResources();
//圖形相關(guān)的
preloadOpenGL();
//一些必要庫
preloadSharedLibraries();
//好像是語言相關(guān)的字符信息
preloadTextResources();
// 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");
}
3:調(diào)用startSystemServer()創(chuàng)建system server進(jìn)程,ams wms pms等常見service都在該進(jìn)程里面扒怖,如下较锡;
private static boolean startSystemServer(String abiList, String socketName) {
//準(zhǔn)備capabilities參數(shù)
........
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=.........",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//將上面準(zhǔn)備的參數(shù),按照ZygoteConnection的風(fēng)格進(jìn)行封裝
parsedArgs = new ZygoteConnection.Arguments(args);
...........
//通過fork"分裂"出system server
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
if (pid == 0) {
............
//pid = 0, 在進(jìn)程system server中
//system server進(jìn)程處理自己的工作
handleSystemServerProcess(parsedArgs);
}
return true;
}
4:調(diào)用runSelectLoopMode()進(jìn)入循環(huán)監(jiān)聽模式盗痒,監(jiān)聽外來請求蚂蕴,如下。
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//首先將server socket加入到fds
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
//關(guān)注事件到來
pollFds[i].events = (short) POLLIN;
}
try {
//等待事件到來
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
//注意這里是倒序的
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
//server socket最先加入fds积糯, 因此這里是server socket收到數(shù)據(jù)
if (i == 0) {
//收到新的建立通信的請求掂墓,建立通信連接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//加入到peers和fds
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//其它通信連接收到數(shù)據(jù),runOnce執(zhí)行對應(yīng)命令
boolean done = peers.get(i).runOnce();
if (done) {
//對應(yīng)通信連接不再需要執(zhí)行其它命令看成,關(guān)閉并移除
peers.remove(i);
fds.remove(i);
}
}
}
}
}
從上面代碼可知君编,初始時,fds中僅有server socket川慌,因此當(dāng)有數(shù)據(jù)到來時吃嘿,將執(zhí)行i ==0 的部分。
此時梦重,顯然是需要創(chuàng)建新的通信連接兑燥,因此acceptCommandPeer將被調(diào)用。
private static ZygoteConnection acceptCommandPeer(String abiList) {
try {
return new ZygoteConnection(sServerSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException("IOException during accept()", ex);
}
}
總結(jié)
1:acceptCommandPeer封裝了socket的accpet函數(shù)琴拧。于是我們知道降瞳,對應(yīng)的新的連接,zygote將會創(chuàng)建出一個新的socket與其通信蚓胸,并將該socket加入到fds中挣饥。因此,一旦通信連接建立后沛膳,fds中將會包含有多個socket扔枫。
2:當(dāng)poll監(jiān)聽到這一組sockets上有數(shù)據(jù)到來時,就會從阻塞中恢復(fù)锹安。于是短荐,我們需要判斷到底是哪個socket收到了數(shù)據(jù)。
3:在runSelectLoop中采用倒序的方式輪詢叹哭,由于server socket第一個被加入到fds忍宋,因此最后輪詢到的socket才需要處理新建連接的操作;其它socket收到數(shù)據(jù)時风罩,僅需要調(diào)用zygoteConnection的runonce函數(shù)執(zhí)行數(shù)據(jù)對應(yīng)的操作讶踪。
4:若一個連接處理完所有對應(yīng)消息后,該連接對應(yīng)的socket和連接等將被移除泊交。
那么從 system server 到 ActivityManager 到 Launcher 又是如何溝通的呢乳讥,也就是第一篇提到的
AMS.startProcessLocked()-->Process.start()-->zygoteSendArgsAndGetResult()-->ZygoteInit.invokeStaticMain(cloader, className, mainArgs)(ActivityThread.main)
system server,具體的過程在介紹system server時再分析