特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。by @宋宝华Barry

上回书我们说到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的看门狗。欲知后事如何,请听下回分解。

谨以本回,献给全天下的有情人,愿有情人终成眷属。对金钱与物质的无限度的追求,让我们迷失了方向,而真正的幸福,是与你的爱人平凡的终生相守。

相思似海深,旧事如天远。
泪滴千千万万行,更使人、愁肠断。
要见无因见,拚了终难拚。
若是前生未有缘,待重结、来生愿。

——宋宝华

更多相关文章

  1. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  2. 关于不需要添加android:debuggable属性就可以进行apk的调试一些
  3. Android内存监测工具DDMS->Heap,内存分析工具->MAT
  4. Android中进程与线程及如何在子线程中操作UI线程
  5. OOM原因和解决方案
  6. Android(安卓)init language(inti.rc语法)
  7. StevGuo系列文章翻译之Android系统属性
  8. android 接触
  9. Android(安卓)的进程与线程

随机推荐

  1. SparseArray详解,我说SparseArray,你说要!
  2. Android中绑定SQLite到ListActivity
  3. window.navigator.userAgent的用处
  4. android 百度推送的集成
  5. Android(安卓)EditText限制输入数字和字
  6. Android基于AudioManager、PhoneStateLis
  7. Android(安卓)Activity分析
  8. android TextInputLayout
  9. 【Android(安卓)Developers Training】 1
  10. Android文件或文件夹内容改变监听器(FileO