Android启动过程详解(4)——SystemServer

上一篇博客介绍了ZygoteService的启动过程,在Zygote的启动后首先就会启动SystemServer,所以SystemServer可以看做是Zygote嫡长子。能够成为嫡长子的必然有着非常重要的作用,的确是这样,Android应用框架中的各种Service,例如ActivityManagerService,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出一个进程作为SystemServer的宿主,具体的操作是在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函数,它由Zygote在fork子进程前调用,代码如下所示:

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

从代码中可以看到,当SystemServer被fork出来之后,会调用handleSystemServerProcess来处理自身的启动逻辑。

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

上面的代码有两个地方比较重要:

  • zygoteInitNative,执行native层的初始化
  • invokeStaticMain(startClass, startArgs):执行SystemServer的main函数。
    接下来分别讲一下以上两点:

2.1 zygoteInitNative

该函数最终会调用AppMain的onZygoteInit函数:

[-->App_main.cpp]
   virtual void onZygoteInit()
    {
        //下面这些东西和Binder有关系
       sp<ProcessState> 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);
}

所以启动过程转移到了init1函数中:
init1是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<ProcessState> proc(ProcessState::self());
   sp<IServiceManager> sm = defaultServiceManager();
   sp<GrimReaper>grim = 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;
}

init1函数创建了一些系统服务,然后把调用线程加入Binder通信中。不过其间还通过JNI调用了com.android.server.SystemServer类的init2函数,下面就来看看这个init2函数。init2在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章。
}

init2函数比较简单,就是单独创建一个线程,用以启动系统各项服务。至此,SystemServer启动完毕。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容