您的位置:首页 > 编程语言 > Go语言

Zygote调用流程分析

2017-05-17 16:00 253 查看

Zygote启动流程

学习总结了老罗的博客以及邓凡平的《深入理解Android操作系统》

先上图。



首先Android开机,init进程解析init.rc文件,读到Zygote的对应配置:

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
onrestart restart media
onrestart restart netd


前面的service告诉init进程去创建一个新的进程,这个进程的名字为zygote,这个zygote进程要运行的程序是
/system/bin/app_process
,后面跟着的是要传给app_process的参数。

socket 关键字说明这个进程需要一个socket资源,名字为紧跟在后面的zygote。

ok,知道了这些,我们就知道
1.main
是如何被调用的啦,近下来,就开始Zygote调用流程的学习。

在app_process的main函数中主要做了两个事

创建
AppRuntime
变量,该变量继承自
AndroidRuntime


调用
AppRuntime
的start函数,实则调用
AndroidRuntime
的start函数

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);
//由于之间的配置文件中谢了-start-system-server
,所以startSystemServer为true
}


AndroidRuntime
的start函数中一次调用如下函数

startVm
启动虚拟机

/* start the virtual machine */

if (startVm(&mJavaVM, &env) != 0) {```


startReg
注册JNI方法

if (startReg(env) < 0) { ```


调动调用了
com.android.internal.os.ZygoteInit
类的main函数

void AndroidRuntime::start(const char* className, const bool startSystemServer) {//claseeName 是上一步传入的com.android.internal.os.ZygoteInit


slashClassName = strdup(className);

startClass = env->FindClass(slashClassName);
```//找到ZygoteInit.class
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
```//找到main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
```//调用ZygoteInit的main方法
}


ZygoteInit
的main方法中依次调用如下方法

调用
registerZygoteSocket
函数创建了一个socket接口,用来和ActivityManagerService通讯

““

public class ZygoteInit {

……

private static final String ANDROID_SOCKET_ENV = “ANDROID_SOCKET_zygote”;

......


private static void registerZygoteSocket() {

if (sServerSocket == null) {

int fileDesc;

try {

String env = System.getenv(ANDROID_SOCKET_ENV);

fileDesc = Integer.parseInt(env);

} catch (RuntimeException ex) {

……

}

try {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
.......
}
}


}

}

““



调用
startSystemServer
函数来启动
SystemServer
组件

““

private static boolean startSystemServer()

throws MethodAndArgsCaller, RuntimeException {

/* Hardcoded command line to start the system server */

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);

......

/* 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) {
......
}

/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);  //子进程的pid为0
}

return true;


}

““

这个函数里fork了一个新的进程,名字是com.android.server.SystemServer



调用
runSelectLoopMode
函数进入一个无限循环,在前面创建的socket接口上等待
ActivityManagerService
请求创建新的应用程序进程

private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];

fds.add(sServerSocket.getFileDescriptor());
peers.add(null);

int loopCount = GC_LOOP_COUNT;
while (true) {
int index;

......

try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}

if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
done = peers.get(index).runOnce();

if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}


到此为止,Zygote进程进入无限循环等待ActivityManagerService来连接这个Socket,然后调用ZygoteConnection.runOnce函数来创建新的应用程序。

SystemService进程

Zygote在
startSystemServer()
中启动了一个新的进程,新的进程执行了
handleSystemServerProcess(parsedArgs);
,接下来看看这个函数干了什么

handleSystemServerProcess(parsedArgs);
函数内部依次执行了如下工作

调用
closeServerSocket
函数关闭从父进程继承过来的文件描述符

public class ZygoteInit {
......

private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();  //关闭从父进程继承过来的socket文件描述符

/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/* should never reach here */
}

......
}


调用
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);


调用
zygoteInitNative
函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了

调用
invokeStaticMain(startClass, startArgs);
执行SystemServer的main函数

public class RuntimeInit {
......

public static final void zygoteInit(String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
......

zygoteInitNative(); // 调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了

......

// Remaining arguments are passed to the start class's static main

String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];

System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
invokeStaticMain(startClass, startArgs); //执行SystemServer的main函数
}

......
}


SystemServer
的main函数中新开一个线程

main函数调用Init1,init1又调用init2,init2开启一个新线程
ServerThread


ServerThread线程对象来执行一些系统关键服务的启动操作,如PackageManagerService和ActivityManagerService。

public class SystemServer
{
......

native public static void init1(String[] args);

......

public static void main(String[] args) {
......

init1(args);

......
}

public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}

......
}




ok,到此为止,就学习总结完了所有流程啦~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: