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,到此为止,就学习总结完了所有流程啦~
相关文章推荐
- eMule源码主要调用流程分析
- USB驱动Suspend&Resume 调用流程分析
- LDD3之scull--从open系统调用到模块的scull_open执行流程分析
- FUSE调用流程分析
- linux网络协议栈分析——ioctl的调用流程
- 利用Anthem.net 实现前台javascript调用服务器端c#函数 及流程分析
- HEVC/H.265整个程序调用流程分析以及函数复杂度分析 .
- zencart v150 文件调用流程(index.php分析)
- Android4.0.3源码分析——开机流程之Zygote
- Zygote工作流程分析
- 从USB设备插上到驱动probe调用流程分析
- Mysql源代码分析系列(3): 主要调用流程--转载
- MySQL源码分析(4):InnoDB主要数据结构及调用流程
- HEVC/H.265整个程序调用流程分析以及函数复杂度分析
- linux网络协议栈分析——ioctl的调用流程
- 利用Anthem.net 实现前台javascript调用服务器端c#函数 及流程分析
- 从USB设备插上到驱动probe调用流程分析
- MySQL5.5-audit plugin的函数调用流程分析
- 2012-11-26 13:06 mahout调用流程分析
- open系统调用在内核中的流程分析