Framework基础:源于异常的System_Server与受精卵Zygote的共存亡

凌乱.png

System_Server是系统进程,而Zygote是Android java世界的基石。这两位都在Android中扮演着十分重要的角色。有个很形象的比喻,Zygote是爸爸,System_Server是大儿子,应用是一堆小儿子就不说了。今天来说说这两位仁兄的两个特性:
1.System_Server使用捕捉异常的方式启动。
2.Zygote与System_Server共存亡。

System_Server使用捕捉异常的方式启动

源文件:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
入口是ZygoteInit的startSystemServer函数,利用forkSystemServer函数产生了子进程SystemServer,并且设置了SystemServer的pid,uid,uidgroud等。但这时并没有进入SystemServer的main函数入口,只是一个进程跑起来了,懂吗。

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        String args[] = {
            "--setuid=1000",   //SystemServer pid=1000,gid=1000,还设置了权限组
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",    //SystemServer的类名
        };
         ...................
         ...................
         //会利用linux的fork函数产生SystemServer子进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //子进程 SystemServer
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }


进入handleSystemServerProcess函数,这里的parsedArgs.remainingArgs就是类名com.android.server.SystemServer

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
            ......
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
           ..................
        }
    }

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
再进入RuntimeInit类的zygoteInit函数

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        commonInit();    //初始化时区啥的
        nativeZygoteInit();  //native的初始化啥的
        applicationInit(targetSdkVersion, argv, classLoader);  //参数argv是类名com.android.server.SystemServer
    }

再进入applicationInit函数

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

再进入invokeStaticMain函数,在这里反射调用了SystemServer类,并且获取到main方法,但并没有执行,而是直接抛出一个异常throw new ZygoteInit.MethodAndArgsCaller。

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
       cl = Class.forName(className, true, classLoader);//反射获取SystemServer类
       Method m;
        m = cl.getMethod("main", new Class[] { String[].class });  //获取main方法
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);   //抛出异常,argv为空
    }

那这个异常是由谁来捕捉呢?其实是在ZygoteInit的main函数捕捉的,如下图

异常捕捉.png

异常捕捉后,调用 caller.run();
这里caller是MethodAndArgsCaller类,是ZygoteInit的内部类。run方法会执行SystemServer的main方法。从而完成SystemServer的启动。


    public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        public void run() {
                mMethod.invoke(null, new Object[] { mArgs });
    }
}

为什么SystemServer要采用捕捉异常的方式启动呢?源码里面其实有注释,应该是启动一个新进程时,用来清除之前的堆栈信息的。

Paste_Image.png

Zygote与System_Server共存亡

System_Server是一个很重要的进程,如果挂了,Zygote必须重启,如果不重启,手机就会进入假死的状态,手机黑屏,无声,无法跟用户交互等。
Zygote与System_Server共存亡是如何实现的呢?
入口:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Zygote调用forkSystemServer产生子进程SystemServer。

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
    }

/frameworks/base/core/java/com/android/internal/os/Zygote.java
进入forkSystemServer函数看看

    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        return pid;
    }

会jni进入native函数
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
 ............................
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL);
 ................................

}

继续进入ForkAndSpecializeCommon函数

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jstring instructionSet, jstring dataDir) {
  ...............
...............
  SetSigChldHandler();   //注册信号,这里将关系共存亡

  pid_t pid = fork();//fork产生子进程systemserver

  if (pid == 0) {
    .........                //子进程的一些操作
  } else if (pid > 0) {
    // the parent process
  }
  return pid;
}

SetSigChldHandler用于注册信号,这里就是关系到Zygote与System_Server的共存亡。

static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;  //信号处理函数

  int err = sigaction(SIGCHLD, &sa, NULL);   
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

SetSigChldHandler定义了信号处理函数SigChldHandler,当信号SIGCHLD到来的时候,会进入信号处理函数。
看看信号处理函数SigChldHandler,可以看到如果子进程SystemServer挂了,Zygote就会自杀。从而完成了共存亡的光辉使命

static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;
 //Zygote监听所有子进程的存亡
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
 //某一个子进程挂了
 if (WIFSIGNALED(status)) {
      if (WTERMSIG(status) != SIGKILL) {
        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
      }
    }
   //如果挂掉的是SystemServer
    if (pid == gSystemServerPid) {
      ALOGE("Exit zygote because system server (%d) has terminated", pid);
      kill(getpid(), SIGKILL);   //Zygote自杀
    }
  }

}

总结

1.System_Server采用抛出异常和捕捉异常的方式启动,可以清除进程的堆栈,减少内存占用。
2.System_Server与Zygote共存亡是通过父进程调用waitpid的方式监听子进程System_Server的死亡,当子进程死亡的时候,父进程就自杀

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

推荐阅读更多精彩内容