Android起動プロセスの詳細(4)-SystemServer

9539 ワード

前のブログではZygoteServiceの起動手順を紹介していましたが、Zygoteの起動後はまずSystemServerが起動するので、SystemServerはZygote嫡男と見ることができます.嫡男の長男になるには必然的に非常に重要な役割があります.確かに、Androidアプリケーションフレームワークのさまざまなサービス、例えばActivity Management Service、PacakgeManagerService、WindowManagerServiceなどの重要なシステムサービスはSystemServerで開始されています.このブログでは、SystemServerの起動手順を見てみましょう.
1.SystemServer起動
SystemServerはZygote.startSystemServerが起動するので、まず対応するコードを見てみましょう.その対応する実装はdalvik_にあります.system_Zygote.cではnative関数です.
[-->dalvik_system_Zygote.c]
static voidDalvik_dalvik_system_Zygote_forkSystemServer(
                        const u4* args, JValue* pResult)
{
     pid_tpid;
    //    ,fork     
    pid =forkAndSpecializeCommon(args);

    if (pid > 0) {
       int status;
       gDvm.systemServerPid = pid;//  system_server   id
      //                     。
        if(waitpid(pid, &status, WNOHANG) == pid) {
           //  system_server   ,Zygote       
           //  Zygote SS       ,       !
            kill(getpid(), SIGKILL);
        }
    }
   RETURN_INT(pid);
}

上記のコードから、Zygoteはシステムサーバのホストとしてプロセスをforkし、具体的な操作はforkAndSpecializeCommonで完了することがわかります.SystemServerの作成プロセスが完了すると、Zygoteは対応するプロセスが終了したかどうかを確認し、終了した場合、Zygoteも自分を殺します.次に、forkAndSpecializeCommonを見てみましょう.コードは次のとおりです.
[-->dalvik_system_Zygote.c]
static pid_t forkAndSpecializeCommon(const u4*args)
{
    pid_tpid;
    uid_tuid = (uid_t) args[0];
    gid_tgid = (gid_t) args[1];
   ArrayObject* gids = (ArrayObject *)args[2];
    u4debugFlags = args[3];
   ArrayObject *rlimits = (ArrayObject *)args[4];

   //      ,          。  
   setSignalHandler();     
    pid =fork(); //fork   
   if (pid== 0) {
     //                 ,       ,    id(  id, id )
   }
......
}

最後にsetSignalHandler関数を見てみましょう.これは、forkサブプロセスの前にZygoteによって呼び出されます.コードは次のようになります.
[-->dalvik_system_Zygote.c]
static void setSignalHandler()
{
    interr;
    structsigaction sa;
   memset(&sa, 0, sizeof(sa));
   sa.sa_handler = sigchldHandler;
    err =sigaction (SIGCHLD, &sa, NULL);//        ,            
}

この信号処理関数sigchldHandlerを直接見て
static void sigchldHandler(int s)
{
    pid_tpid;
    intstatus;

    while((pid = waitpid(-1, &status, WNOHANG)) > 0) {
             } else if (WIFSIGNALED(status)) {
          }
        }
        //         SS, Zygote       ,          !
        if(pid == gDvm.systemServerPid) {
           kill(getpid(), SIGKILL);
        }
   }

2.SystemServerの役割
次に、SystemServerが起動中に具体的に何をしたかを見てみましょう.
pid =Zygote.forkSystemServer();
     if(pid == 0) { //       :
           handleSystemServerProcess(parsedArgs);
    }

コードから分かるように、システムサーバがforkされると、handleSystemServer Processが呼び出され、自身の起動ロジックが処理されます.
[-->ZygoteInit.java]
private static void handleSystemServerProcess(
       ZygoteConnection.ArgumentsparsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {
      //   Zygote       Socket。 
      closeServerSocket();
      //  SS       。
      setCapabilities(parsedArgs.permittedCapabilities,
                   parsedArgs.effectiveCapabilities);
        //  ZygoteInit  。
      RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
  }

よし、SSはRuntimeInitに着いた.そのコードはRuntimeInitにある.JAvaでは、以下のようになります.
[-->RuntimeInit.java]
public static final void zygoteInit(String[]argv)
           throws ZygoteInit.MethodAndArgsCaller {
     //        
     commonInit();
     //①native     。
    zygoteInitNative();
     intcurArg = 0;
     for (/* curArg */ ; curArg < argv.length; curArg++) {
           String arg = argv[curArg];
           if (arg.equals("--")) {
               curArg++;
               break;
           } else if (!arg.startsWith("--")) {
               break;
           } else if (arg.startsWith("--nice-name=")) {
               String niceName = arg.substring(arg.indexOf('=') + 1);
               //      niceName,   "system_server"
               Process.setArgV0(niceName);
           }
        }
       //startClass  "com.android.server.SystemServer"
       String startClass = argv[curArg++];
       String[] startArgs = new String[argv.length - curArg];
       System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
       //②  startClass,   com.android.server.SystemServer  main  。
       invokeStaticMain(startClass, startArgs);
}

上のコードには2つの点が重要です.
  • zygoteInitNative,nativeレイヤの初期化
  • を実行する.
  • invokeStaticMain(startClass,startArgs):SystemServerのmain関数を実行します.次に、以上の2点をそれぞれ説明します.
  • 2.1 zygoteInitNative
    この関数は最終的にAppMainのonZygoteInit関数を呼び出します.
    [-->App_main.cpp]
       virtual void onZygoteInit()
        {
            //       Binder   
           sp proc = ProcessState::self();
            if(proc->supportsProcesses()) {
                proc->startThreadPool();//      ,  Binder  。
           }      
    }
    

    2.2 invokeStaticMain
    [-->RuntimeInit.java]
    private static void invokeStaticMain(StringclassName, String[] argv)
               throws ZygoteInit.MethodAndArgsCaller {
          ......
          //className "com.android.server.SystemServer"
           Class> cl;
           
           try {
               cl = Class.forName(className);
            }catch (ClassNotFoundException ex) {
               throw new RuntimeException(
                        "Missing class wheninvoking static main " + className,
                        ex);
            }
    
           Method m;
           try {
               //  com.android.server.SystemServer  main  ,         
               m = cl.getMethod("main", new Class[] { String[].class });
            }catch (NoSuchMethodException ex) {
               ......
            }catch (SecurityException ex) {
               ......
            }
    
           int modifiers = m.getModifiers();
           if(! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
               ......
            }
            //      
           throw new ZygoteInit.MethodAndArgsCaller(m, argv);
        }
    

    この関数が奇妙な点は、com.android.server.SystemServerクラスにロードされ、対応するmain関数が見つかった後、直接関数を起動するのではなく、ZygoteInitのmain関数でcatchされ、対応する面関数が起動される異常を投げ出したことです.これはスタックを空にするためであり,スタックのスタックトップがZygoteInitであることをユーザに見せるためである.main.
    次にZygoteが起動した後に何をしたかを見てみましょう.まずmain関数を見てみましょう.
    [-->SystemServer.java]
    public static void main(String[] args) {
       ......
       //  libandroid_servers.so
       System.loadLibrary("android_servers");
       //  native init1  。
       init1(args);
    }
    

    だから起動プロセスはinit 1関数に移行しました:init 1はnative関数で、com_android_server_SystemServer.cppで実装:
    [-->com_android_server_SystemServer.cpp]
    extern "C" int system_init();
    static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)
    {
       system_init();//        。
    }
    

    system_Initの実装はsystem_init.cppでは、そのコードを以下に示します.
    [-->system_init.cpp]
    extern "C" status_t system_init()
    {
       //       Binder  ,     6    ,       。
       sp proc(ProcessState::self());
       sp sm = defaultServiceManager();
       spgrim = new GrimReaper();
       sm->asBinder()->linkToDeath(grim, grim.get(), 0);
       charpropBuf[PROPERTY_VALUE_MAX];
       property_get("system_init.startsurfaceflinger", propBuf,"1");
    
        if(strcmp(propBuf, "1") == 0) {
            //SurfaceFlinger   system_server    
           SurfaceFlinger::instantiate();
        }
         ......
    
        //  com.android.server.SystemServer  init2  
       AndroidRuntime* runtime =   AndroidRuntime::getRuntime();
       runtime->callStatic("com/android/server/SystemServer","init2");
    
    //          Binder    。
    
        if (proc->supportsProcesses()) {
            ProcessState::self()->startThreadPool();
           //  joinThreadPool ,        Binder      
           IPCThreadState::self()->joinThreadPool();
           }
        returnNO_ERROR;
    }
    

    Init 1関数はいくつかのシステムサービスを作成し,呼び出しスレッドをBinder通信に組み込む.しかしその間にJNIを介してcomが呼び出された.android.server.SystemServerクラスのinit 2関数ですが、このinit 2関数を見てみましょう.Init 2はJava層にあり、コードはSystemServerにある.JAva:
    [-->SystemServer.java]
    public static final void init2() {
       Threadthr = new ServerThread();
       thr.setName("android.server.ServerThread");
       thr.start();//    ServerThread
    }
    

    ServerThreadスレッドが起動しました.そのrun関数を直接見てください.この関数は長いので、何をしたか見てみましょう.
    [-->SystemServer.java::ServerThread run  ]
    public void run(){
                 ....
      //  Entropy Service
      ServiceManager.addService("entropy",new EntropyService());
      //        
      power =new PowerManagerService();
     ServiceManager.addService(Context.POWER_SERVICE, power);
      //        。
      battery= new BatteryService(context);
     ServiceManager.addService("battery", battery);
    
       //      
       Watchdog.getInstance().init(context,battery, power, alarm,
                                   ActivityManagerService.self());
    
      //  WindowManager  
      wm =WindowManagerService.main(context, power,
                        factoryTest !=SystemServer.FACTORY_TEST_LOW_LEVEL);
     ServiceManager.addService(Context.WINDOW_SERVICE,wm);         
    
      //  ActivityManager  
    (ActivityManagerService)ServiceManager.getService("activity")).setWindowManager(wm);
      ......//              
    
       Looper.loop();  //      ,      。          5 。
    }
    

    Init 2関数は比較的簡単で、システムの各サービスを開始するためにスレッドを個別に作成します.これでシステムサーバの起動が完了します.