杭州华育LOGO

学员作品 学员心得 技术园地 潮人地 Android(安卓)培训 杭州电脑(计算机)培训 杭州网络营销培训 杭州JAVA培训
返回首页

Android架构纵横谈之——软件自愈能力 (2)

时间:2012-07-19 10:59来源:51cto 作者:宋宝华 点击:
本讲宋宝华接着为我们的学员们讲解Android架构的一些具体的细节,里面运用了很多生活中的一些常识,讲生活中的一些事情与软件开发,特别是Android培训结合在一起,相信能进一步吸引大家跟好的学习Android。

上回书我们说到Android里的init会监测init.rc中启动的service并根据情况重启之。今回书我们说Android中生死与共的Zygote和SystemServer。

第二只狗:忠犬八公

方 今之世,正道不昌,邪魔丛生。撞伤不如撞死,因此各种难以理解之行为层出不穷,撞后用天涯明月刀杀人者有之,撞后人民女教师裸体阻救援者有之,这是怎样地 一种非人间的浓厚的悲凉?对人生命权的尊重实为较基础之人性,残杀同类,见死阻救,实为丧失较基础之人性。热泪在心中,汇成河流。我们曾经以无限崇高的主 义,无比正义的革命的名义杀人,肆意践踏人较基本的尊严,而悲剧的后果是,热血已成过去,激情亦然淡去,主义仍如浩渺 ,人性却遭沦丧。

人性已泯,狗性依然,如太平洋的风。本回书,我们说第二只狗,忠犬八公。1925年5月,八公的主人上野因病猝然去世,然而八公犬并不懂人事,依然每天到涩谷站去等候主人的归来。直到较后死去。1935年3月,八公因患丝虫性象皮病而死亡。十年生死两茫茫,不思量,自难忘。所谓爱者,大抵如此。在这个小三流行的世界,什么样的人还珍视婚姻的责任和当初的誓言?

本回书我们要谈的是Zygote和SystemServer的生死与共,执子之手,与子偕老,Zygote和SystemServer用全部的生命来演绎这段忠贞的爱情,当死去时,与子成蝶,如果有来生,我们还在一起。

Zygote是Android系统的核心,受精卵的意思,Android framework大家族的祖先。她的妈贵姓呢?就是上回书里说的init。Zygote是Java世 界的生产者,Android的女娲,她通过runSelectLoopMode()不断监听来自应用程序的透过 ActivityManagerService的启动需求,并fork出相应的进程。而SystemServer是Android世界里的核心价 值,SurfaceFlinger以及Java服务如PowerManagerService、 WindowManagerService、ActivityManagerService等都是他启动的,并成为他的一部分,他带的嗷嗷叫的兵,共同位 于SystemServer进程空间。可以说,SystemServer的崩溃基本意味着Android的Framework的崩溃。 SystemServer是Android里兵马大元帅。基本上,在Android的世界里,能与SystemServer和Zygote彼此相配的,也 就只有对方。那么SystemServer百战而死后,Zygote应该是万念俱灰,其实真地没有活着的必要。

在Android中,SystemServer是由 Zygote分叉出来的,相关代码位于dalvik/vm/native/dalvik_system_Zygote.c中:

static void Dalvik_dalvik_system_Zygote_forkSystemServer(
        const u4* args, JValue* pResult)
{
    pid_t pid;
    pid = forkAndSpecializeCommon(args, true);

    /* The zygote process checks whether the child process has died or not. */
    if (pid > 0) {
        int status;

        LOGI("System server process %d has been created", pid);
        gDvm.systemServerPid = pid;
        /* There is a slight window that the system server process has crashed
         * but it went unnoticed because we haven't published its pid yet. So
         * we recheck here just to make sure that all is well.
         */
        if (waitpid(pid, &status, WNOHANG) == pid) {
            LOGE("System server process %d has died. Restarting Zygote!", pid);
            kill(getpid(), SIGKILL);
        }
    }
    RETURN_INT(pid);
}
 

其中的forkAndSpecializeCommon()会fork出 SystemServer,Zygote马上用waitpid(pid, &status,WNOHANG)等待SystemServer的死亡,注意其中的参数为WNOHANG,意思就是说等不等地到 SystemServer退出,waitpid()都不会阻塞,如果发现SystemServer死了,它会无条件调用kill(getpid(), SIGKILL)殉情。这个瞬间的等待按照注释是为了防止很小的一段时间窗口里,真正等SystemServer死的代码还没注意到 SystemServer的PID。SIGKILL牛就牛在是不能被忽略的信号,这点和CTRL+C对应的SIGINT不同。

有些同学就要 问了,一个进程莫名其妙地kill掉了自己,有时候我们还强行用kill命令去杀死Linux的进程,这个时候它原本申请的内存什么的,不是泄露了吗?譬 如我malloc了一些内存,你杀死我的时候我还没free,这些内存不是侧露了吗?我已经反复在各个公司演讲的时候说了,内存泄露分为两种境界,一个是 人死了,钱还没花完,你malloc的内存还没释放进程就死了,我们说,这个问题在Linux不存在,进程是个资源封装的单位,进程挂的时候,资源会被内 核释放掉的,死的时候还仅仅有个僵尸而已。第二个境界是,人活着,钱没了,这个问题才是Linux真正担心的,一个多线程的程序,运行过程中反复申请和释 放内存,但是释放的与申请的不对应,就慢慢地吃内存,这个进程的内存消耗曲线振荡上升,直到耗尽内存。所以,在Linux世界里,我们不用担心人死了,钱 还没花完的问题 ,党会帮我们处理的。我们要担心的是,人活着,钱没了的问题。

话说HTC Android手机号称的1秒快速启动,根据我们的跟踪就是关机时候杀进程,然后suspend,之后resume回来,由于前面进程都杀了,所以你看到个干净的桌面。所以,神马都是浮云啊。你收回了黄岩岛,油价还是要涨的,他们会说我们是花了钱收回来的。

废话少说,你刚才还说Zygote和SystemServer 生死与共,怎么就才等了一下呢?不是要负责一辈子的吗?我们回到forkAndSpecializeCommon(),继续挖掘:

static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
   …

    setSignalHandler();

    dvmDumpLoaderStats("zygote");
    pid = fork();

    if (pid == 0) {
        int err;
        /* The child process */

        …
    }
    return pid;
}
 

其中的setSignalHandler()会设置SIGCHLD的信号处理函数,而这个信号处理函数就会判断是否SystemServer死了,如果是,就自杀殉情:

static void setSignalHandler()
{
    int err;
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));

    sa.sa_handler = sigchldHandler;

    err = sigaction (SIGCHLD, &sa, NULL);

    if (err < 0) {
        LOGW("Error setting SIGCHLD handler: %s", strerror(errno));
    }
}
static void sigchldHandler(int s)
{
    pid_t pid;
    int status;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        …
        /*
         * If the just-crashed process is the system_server, bring down zygote
         * so that it is restarted by init and system server will be restarted
         * from there.
         */
        if (pid == gDvm.systemServerPid) {
            LOG(LOG_INFO, ZYGOTE_LOG_TAG,
                "Exit zygote because system server (%d) has terminated\n",
                (int) pid);
            kill(getpid(), SIGKILL);
        }
    }

    …
}
 

当SystemServer死去,Zygote的花轿在它坟前路过,见Zygote走出轿来,脱去红装,一身素 服,缓缓地走到坟前, 跪下来放声大哭,霎时间风雨飘摇,雷声大作,“轰”的一声,坟墓裂开了,Zygote似乎又见到了SystemServer那温柔的面庞,她微笑着纵身跳 了进去。接着又是一声巨响,坟墓合上了。这时风消云散,雨过天晴,各种野花在风中轻柔地摇曳,一对美丽的蝴蝶从坟头飞出来,在阳光下自由地翩翩起舞。

当Zygote也死去,由于Zygote是有户口的,上回书中的第一只狗, 肩负其使命,会重启Zygote,于是SystemServer也随Zygote重启,生生世世不分离。

这里要特别说明的是,当Zygote死去的时候,上回书中的init中的wait_for_one_process()会透过给 “- zygote_pid”发SIGKILL,从而杀死Zygote对应的进程组,因此整个Java世界都宣告结束:

static int wait_for_one_process(int block)
{
    ...

    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
    ...

    if (!(svc->flags & SVC_ONESHOT)) {
        kill(-pid, SIGKILL);
        NOTICE("process '%s' killing any children in process group\n", svc->name);
    }

   ...

}

由于几乎所有的Java应用都依赖于SystemServer中的service,如果 SystemServer崩溃,Zygote不死并且不导致整个Java世界死亡,实际上系统没有任何办法把状态恢复到SystemServer崩溃之前 的状态 ,那么各个apk所看到的SystemServer中各个service的状态也无法恢复,所以整个Java世界死亡并重启就成为优先的选择。

本回书就说到这里,下回书我们说SystemServer的看门狗。欲知后事如何,请听下回分解。

未完待续

(责任编辑:杭州华育 ;杭州java培训,网络营销培训,杭州计算机培训,it培训,详询客服报名咨询
分享到:
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
提交报名信息

2018年杭州将加大力度经济转型,吸纳更多的技术人才落户杭州,软件人才需求量更是大幅提升,针对目前杭州IT行业人才需求“井喷”现象,华育软件杭州实训基地与杭州155家IT名企合作,建立人才培养与输送关系,启动“Eduask国家高端IT紧缺人才培养工程”。4月针对杭州地区18-28岁大中专生待业青年发放68个技能实训名额(应届大中专毕业生优先),经短期专业岗前实训后推荐进入企业,起薪4500-8000元,五险一金。

姓名: * 性别:
学历: 电话: *
所在地: *
您目前状况:
留言:
*