Step 2.AndroidRuntime.start

这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

        
  1. /*
  2. *StarttheAndroidruntime.Thisinvolvesstartingthevirtualmachine
  3. *andcallingthe"staticvoidmain(String[]args)"methodintheclass
  4. *namedby"className".
  5. */
  6. voidAndroidRuntime::start(constchar*className,constboolstartSystemServer)
  7. {
  8. ......
  9. char*slashClassName=NULL;
  10. char*cp;
  11. JNIEnv*env;
  12. ......
  13. /*startthevirtualmachine*/
  14. if(startVm(&mJavaVM,&env)!=0)
  15. gotobail;
  16. /*
  17. *Registerandroidfunctions.
  18. */
  19. if(startReg(env)<0){
  20. LOGE("Unabletoregisterallandroidnatives\n");
  21. gotobail;
  22. }
  23. /*
  24. *Wewanttocallmain()withaStringarraywithargumentsinit.
  25. *Atpresentweonlyhaveoneargument,theclassname.Createan
  26. *arraytoholdit.
  27. */
  28. jclassstringClass;
  29. jobjectArraystrArray;
  30. jstringclassNameStr;
  31. jstringstartSystemServerStr;
  32. stringClass=env->FindClass("java/lang/String");
  33. assert(stringClass!=NULL);
  34. strArray=env->NewObjectArray(2,stringClass,NULL);
  35. assert(strArray!=NULL);
  36. classNameStr=env->NewStringUTF(className);
  37. assert(classNameStr!=NULL);
  38. env->SetObjectArrayElement(strArray,0,classNameStr);
  39. startSystemServerStr=env->NewStringUTF(startSystemServer?
  40. "true":"false");
  41. env->SetObjectArrayElement(strArray,1,startSystemServerStr);
  42. /*
  43. *StartVM.ThisthreadbecomesthemainthreadoftheVM,andwill
  44. *notreturnuntiltheVMexits.
  45. */
  46. jclassstartClass;
  47. jmethodIDstartMeth;
  48. slashClassName=strdup(className);
  49. for(cp=slashClassName;*cp!='\0';cp++)
  50. if(*cp=='.')
  51. *cp='/';
  52. startClass=env->FindClass(slashClassName);
  53. if(startClass==NULL){
  54. ......
  55. }else{
  56. startMeth=env->GetStaticMethodID(startClass,"main",
  57. "([Ljava/lang/String;)V");
  58. if(startMeth==NULL){
  59. ......
  60. }else{
  61. env->CallStaticVoidMethod(startClass,startMeth,strArray);
  62. ......
  63. }
  64. }
  65. ......
  66. }

这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

Step 3.ZygoteInit.main

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

        
  1. publicclassZygoteInit{
  2. ......
  3. publicstaticvoidmain(Stringargv[]){
  4. try{
  5. ......
  6. registerZygoteSocket();
  7. ......
  8. ......
  9. if(argv[1].equals("true")){
  10. startSystemServer();
  11. }elseif(!argv[1].equals("false")){
  12. ......
  13. }
  14. ......
  15. if(ZYGOTE_FORK_MODE){
  16. ......
  17. }else{
  18. runSelectLoopMode();
  19. }
  20. ......
  21. }catch(MethodAndArgsCallercaller){
  22. ......
  23. }catch(RuntimeExceptionex){
  24. ......
  25. }
  26. }
  27. ......
  28. }

它主要作了三件事情,一个调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯,二是调用startSystemServer函数来启动SystemServer组件,三是调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

Step 4.ZygoteInit.registerZygoteSocket

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

        
  1. publicclassZygoteInit{
  2. ......
  3. /**
  4. *Registersaserversocketforzygotecommandconnections
  5. *
  6. *@throwsRuntimeExceptionwhenopenfails
  7. */
  8. privatestaticvoidregisterZygoteSocket(){
  9. if(sServerSocket==null){
  10. intfileDesc;
  11. try{
  12. Stringenv=System.getenv(ANDROID_SOCKET_ENV);
  13. fileDesc=Integer.parseInt(env);
  14. }catch(RuntimeExceptionex){
  15. ......
  16. }
  17. try{
  18. sServerSocket=newLocalServerSocket(
  19. createFileDescriptor(fileDesc));
  20. }catch(IOExceptionex){
  21. .......
  22. }
  23. }
  24. }
  25. ......
  26. }

这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,它定义为:

  1. publicclassZygoteInit{
  2. ......
  3. privatestaticfinalStringANDROID_SOCKET_ENV="ANDROID_SOCKET_zygote";
  4. ......
  5. }

那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的:

  1. voidservice_start(structservice*svc,constchar*dynamic_args)
  2. {
  3. ......
  4. pid_tpid;
  5. ......
  6. pid=fork();
  7. if(pid==0){
  8. structsocketinfo*si;
  9. ......
  10. for(si=svc->sockets;si;si=si->next){
  11. intsocket_type=(
  12. !strcmp(si->type,"stream")?SOCK_STREAM:
  13. (!strcmp(si->type,"dgram")?SOCK_DGRAM:SOCK_SEQPACKET));
  14. ints=create_socket(si->name,socket_type,
  15. si->perm,si->uid,si->gid);
  16. if(s>=0){
  17. publish_socket(si->name,s);
  18. }
  19. }
  20. ......
  21. }
  22. ......
  23. }

每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:

  1. staticvoidpublish_socket(constchar*name,intfd)
  2. {
  3. charkey[64]=ANDROID_SOCKET_ENV_PREFIX;
  4. charval[64];
  5. strlcpy(key+sizeof(ANDROID_SOCKET_ENV_PREFIX)-1,
  6. name,
  7. sizeof(key)-sizeof(ANDROID_SOCKET_ENV_PREFIX));
  8. snprintf(val,sizeof(val),"%d",fd);
  9. add_environment(key,val);
  10. /*makesurewedon'tclose-on-exec*/
  11. fcntl(fd,F_SETFD,0);
  12. }

这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:#defineANDROID_SOCKET_ENV_PREFIX"ANDROID_SOCKET_" 因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了,参考Android应用程序进程启动过程的源代码分析一文中的Step 4,ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:

        
  1. publicclassProcess{
  2. ......
  3. privatestaticvoidopenZygoteSocketIfNeeded()
  4. throwsZygoteStartFailedEx{
  5. ......
  6. for(intretry=0
  7. ;(sZygoteSocket==null)&&(retry<(retryCount+1))
  8. ;retry++){
  9. ......
  10. try{
  11. sZygoteSocket=newLocalSocket();
  12. sZygoteSocket.connect(newLocalSocketAddress(ZYGOTE_SOCKET,
  13. LocalSocketAddress.Namespace.RESERVED));
  14. sZygoteInputStream
  15. =newDataInputStream(sZygoteSocket.getInputStream());
  16. sZygoteWriter=
  17. newBufferedWriter(
  18. newOutputStreamWriter(
  19. sZygoteSocket.getOutputStream()),
  20. 256);
  21. ......
  22. }catch(IOExceptionex){
  23. ......
  24. }
  25. }
  26. ......
  27. }
  28. ......
  29. }

这里的ZYGOTE_SOCKET定义为:

  1. publicclassProcess{
  2. ......
  3. privatestaticfinalStringZYGOTE_SOCKET="zygote";
  4. ......
  5. }

它刚好就是对应/dev/socket目录下的zygote文件了。

Android系统中的socket机制和binder机制一样,都是可以用来进行进程间通信,读者可以自己对比一下这两者的不同之处,Binder进程间通信机制可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。

Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。

更多相关文章

  1. 从J2EE转向Android的第九天-----文件存储
  2. android 进程间通信示例
  3. Android笔记四 虚拟机Dalvik、Android各种java包功能、Android相
  4. Android系统进程Zygote启动过程的源代码分析
  5. android保存手势操作到文件&读取识别手势
  6. 一定是我打开的姿势不对——Android下使用kill命令杀死指定进程
  7. Android使用AIDL跨进程数据共享

随机推荐

  1. 如果没有 Android,世界会怎样?
  2. Android学习笔记1---简单计算器
  3. 在ubuntu上安装google play和安卓应用
  4. Android(安卓)项目导入eclipse中报错但找
  5. Android拍照实现方式概述
  6. ANDROID中按键的添加配置(linux按键到andr
  7. 利用HTML5开发Android笔记
  8. Android中原始资源文件使用详解
  9. Android设备之间通过Wifi通信的示例代码
  10. Android小项目之--找到本地联络人并向其