第三天,google说,伊甸园(linux世界)要被隔离,于是便创造了亚当(Adm)与夏娃(Eve),称它为zygote和system_server

--xxx

第二天,init跑完了,它对于android系统,最重要的,就是启动了zygote和system-server,谁是Adam谁是Eve?

从分析init.rc来看

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

--start-system-server只是个参数。

分析源码

啊,原来夏娃(zygote)用自己的肋骨(fork)创造了亚当(system_server)!什么?为什么不是亚当创造夏娃!? android的世界,是无性繁殖的世界,zygote(夏娃)一开始就是个受精卵。。。。。。。

Eve诞生记(zygote启动过程)

第一步,受精(改名)

从init.rc可以看出,启动的是app_process程序,启动后,再把自己的进程名改为zygote,就算是受精了。。

第二步,着床(交由AppRuntime启动javaVM)

这时,会创建一个vm,算是android java世界的祖师爷,并且在这个vm启动时赋予各种参数,比如我们都知道默认的情况下,一个应用程序加载的内存不能超过16mb,这个参数就是在这里设置的,heapsize为16mb。这之后vm就启动了,哦,应该叫dalvik。

在启动后,还会为java的类注册JNI函数,android世界是c与java互相交织的。

第三步,生长脐带(初涉java世界)

注册好各种JNI函数后,zygote的C层面就可以调用Java代码了。

这里第一次进入了java世界。它调用了 com.android.internal.os.ZygoteInit 的main方法。

java世界并不孤立

1、它首先注册socket,使自己成为一个服务端,也就是IPC通信服务端。这就是android的伟大之处,巧妙利用了linux的所有特性。以后会讲到zygote的真谛。

2、然后预加载类以及一些android资源。洋洋洒洒1k多个java类要加载,并且还都是加载时间大于1250微妙的类,android框架加载耗时的类都到这里来加载了,这也正是android开机慢得原因,不过苦尽甘来吗,开始累点能干的都干了,以后用起来就方便了,不是么?当然,android的系统就像是量产车,各种性能不求最好只求最稳定,广大发烧友改rom就像改装汽车一样,需要精通从齿轮组到ECU的各种知识,方能达到硬件与软件完美的结合以便发挥出最大功效,扯多了。。要想定制rom,减少开机时间,还得靠nb的水平与良好的洞察力。

3、启动SystemServer。也就是system_server进程。

刚才说了,这个system_server就是Adm,夏娃的第一块肉就这么掉下来了,同样利用linux的fork机制,从zygote进程分裂出了一个system_server进程。男女搭配干活不累,亚当与夏娃共同劳动,为我们搭建美好的android世界。

后面会分析system_server都干些什么事。

4、建一个线程,转入socket侦听模式。每个apk在android中运行起来都是一个单独的linux进程,这些进程,就是zygote分裂出来的。现在zygote侦听的就是ActivityService通过system_server使用socket传入的请求,用以分裂进程。线程之外的最后,关闭之前打开的socket侦听。

现在夏娃该干的事,基本上干完了,就等着亚当再次让她受精了。。。。。 -_-!!!!

这里就顺便描述下每个Activity分娩出来的过程吧!(Activity大致启动过程)

step 1 凡人向神求仔:

启动一个activity,也就是startActivity。这个activity依附于一个未启动的进程,好比刚开机,打开一个android程序。

step 2 大神收到祈愿:

ActvityManagerService收到startActvity,梳理一番各种参数,比如apk的报名,再将这个祈愿通过送到伊甸园交由夏娃实施。

step3 伊甸园接到生仔请求:

亚当愿意别人直接找夏娃么?呵呵,各种service都是SystemServer启动起来的,而SystemServer又掌管着Binder,自己肯定会首先处理这个通知的。SystemServer通过socket这个IPC机制,向zygote发送一个fork请求,这时从java世界回到了native世界,亚当(system_server)让夏娃(zygote)受精了。。。。 -_-!!! android的繁荣离不开这种造仔活动

step4 夏娃生仔:

又要分裂了,fork出了一个新进程,并把这个进程返还给Java世界,并且由ActivityManagerService管理它。这里,就是让这个进程调用ActivityThread,ActvityThread就是main,apk程序的main。

linuix中fork出来的子进程会继承父进程的所有信息,就相当于一个拷贝,只不过变成了另一个进程。既然继承了所有信息,那么dalvik也就继承下来了,这就解释了为什么一个android程序都有一个vm进程。

Adam诞生记(SystemServer启动过程)

上面提到zygote在java层启动并fork了SystemServer,也就是夏娃身上掉下来的第一块肉。

SystemServer首先会关闭因fork而从父进程继承而来的socket。

第一步,Native层初始化

这里会通过JNI调用native方法,又回到了Native世界。

首先,初始化Skia引擎,就是一个图像引擎,封装了画图的各种操作,这样屏幕就能让显示东西了。

然后,启动Binder,也就是android IPC的核心。

第二步,换名,并进行JAVA层初始化

换名了,这个vm进程就被正式命名为system_server了。

java层初始化,也就是调用 com.android.server.SystemServer 的main。有趣的是,这里通过反射,获得SystemServer类的main方法后,不直接调用,而是抛出一个异常,这个异常包含了main这个Method。

再回头看看zygote的java世界,启动了system_server的代码是在try中,catch中就是截获上面所说的异常,并执行main的这个Method。

为什么这么做?

先来看个示例程序:

public class Method_test {public static void main(String[] args) {ClassA ca=new ClassA();ca.start();}}class ClassA{public ClassA() {}public void start(){System.out.println("开始调用方法");Method_A();}public void Method_A(){System.out.println("方法A被调用");Method_B();}public void Method_B(){System.out.println("方法B被调用");Method_C();}public void Method_C(){System.out.println("方法C被调用");Method_final();}public void Method_final(){System.out.println("最终方法被调用");}}

上面这段代码模拟一个一个场景,方法A调用B,B又调用了C。。。 A()->B()->C()->final(),final里面可能又有更复杂的内容,而且final之后基本上不做什么了。真实情况下,A()与final()之间还有更多的调用层次。

上面的调用栈情况是这样的:

这样的话,在一些资源稀缺的平台上,,,,的确不怎么好,我们希望执行final的时候,前面调用的层次能消失,以前用过的变量什么也消失,还我们一个清净的世界,而且执行完了也不用再层层跳出了。

这时,try catch就有大作用了,看代码:

public class Method_test {public static void main(String[] args) {ClassA ca=new ClassA();ca.start();}}class ClassA{public ClassA() {}public void start(){System.out.println("开始调用方法");try{Method_A();}catch (RuntimeException e) {//捕获异常后再执行目标方法Method_final();}}public void Method_A(){System.out.println("方法A被调用");Method_B();}public void Method_B(){System.out.println("方法B被调用");Method_C();}public void Method_C(){System.out.println("方法C被调用");//这里抛出一个异常throw new RuntimeException();}public void Method_final(){System.out.println("最终方法被调用");}}

与之前相比,把final()的调用换到了start()里,直接让c()抛出个异常,catch中执行final()。

调用栈如下:

Android的设计思想真猛啊,通过这么分析,又学到一个技巧。。。。

SystemService->main

1、加载native库并调用init1()

这里创建了几个native服务, ServiceManger、SurfaceFlinger等,并把当前线程加入到Binder的通信大军中。

2、通过JNI调用JAVA世界的init2()

在上面的init1()中,最后会调用java世界的init2()。

这里就是启动各种服务了,什么EntropyService、PowerManagerService、BatteryService、WindowManager等等。

还会把地狱犬召唤出来,也就是WatchDog(看门狗),来时刻盯着一些重要的Service,防止他们堕落。看门狗的职责就是盯着一些重要的service,万一他们挂了,就把亚当杀死,然后让init把它再原地满血复活。

最后,就进入了消息循环,负责android世界中跨线程访问的调度,google常曰 子线程要通过handler来更新UI线程,那么handler中发送的消息就是靠这里来分发的。

这里严重推荐 邓凡平 前辈所著的《深入理解Anroid 卷I》,我自己感觉这是我见过的涉及框架的最好的一本书,主要就是通俗易懂啊(其实还是自己的水平有限)

水平有限,错误之处请指正,多谢!

  创世纪:第一天连接:http://www.cnblogs.com/hangxin1940/archive/2011/10/01/2196964.html

  创世纪:第二天连接:http://www.cnblogs.com/hangxin1940/archive/2011/10/14/2196964.html

##第四天链接,占位##

原创文章,转载请说明出处:

http://www.cnblogs.com/hangxin1940/archive/2011/10/01/2196964.html

更多相关文章

  1. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  2. android binder相关
  3. 最新Android(安卓)出现Please ensure that adb is correctly loc
  4. Android(安卓)Studio使用aidl实现进程间通信
  5. android ApiDemo学习(一)service——6 Remote Service Controller
  6. Android开发常用调试技术记录
  7. Android(安卓)Binder设计与实现(1) – 设计篇
  8. android 常见死机问题-如何分析
  9. Android(安卓)进程间通信AIDL学习

随机推荐

  1. Android系统源码下载与编译、刷机--Nexus
  2. android输入子设备类型
  3. android UI属性:inputType
  4. Android(安卓)Audio - 支持多应用同时录
  5. android FAILED Binder Transaction 问题
  6. Android SDK、NDK、JNI的简单介绍
  7. android TextView 的setTextSize方法的使
  8. Android battery historian功耗分析之环
  9. 通过ant脚本编译打包android工程
  10. Android(安卓)动画1--View控件的显示和隐