Android 创世纪 第三天

标签: android 创世纪 | 发表时间:2011-10-22 22:00 | 作者:黑暗伯爵 英建
出处:http://www.cnblogs.com/

第三天,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的frok机制,从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发送一个frok请求,这时从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中,catach中就是截获上面所说的异常,并执行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

作者: 黑暗伯爵 发表于 2011-10-22 22:00 原文链接

评论: 0 查看评论 发表评论


最新新闻:
· 我相信 Google+(2011-10-23 14:47)
· 乔布斯想要毁灭Android(2011-10-23 14:37)
· 德国卫星将从天空坠落(2011-10-23 14:34)
· 摩托罗拉确认Xoom平板将升级Android 4.0(2011-10-23 14:30)
· 乔布斯对 Larry Page 的建议:精简产品(2011-10-23 12:26)

编辑推荐:消灭程序员需要百年吗?

网站导航:博客园首页  我的园子  新闻  闪存  小组  博问  知识库

相关 [android 创世纪] 推荐:

Android 创世纪 第一天

- Adam - 博客园-首页原创精华区
第一天,google说,要有电,于是电流涌向了电路板,涌入了arm处理器,于是arm运作了.     嵌入式世界诞生之出,世界是荒蛮的,电流涌向各个芯片,各种处理器等待着唤醒.     arm觉醒了,开始审视自己.         ---------------下面内容可能有误,请指正-------------------.

Android 创世纪 第二天

- jejer - 博客园-首页原创精华区
第二天,google说,荒芜要被开垦,系统便运作了,它是linux.      荒蛮大地就要变得肥沃,linux已经运行起来了.      linux就不多讲了,这里只讲讲被google大刀阔斧改了内核后的linux.      第一天最后,内核init已经干完了自己的事,把控制权交给了第一个用户级进程,也叫做init.

Android 创世纪 第三天

- 英建 - 博客园-首页原创精华区
第三天,google说,伊甸园(linux世界)要被隔离,于是便创造了亚当(Adm)与夏娃(Eve),称它为zygote和system_server.      第二天,init跑完了,它对于android系统,最重要的,就是启动了zygote和system-server,谁是Adam谁是Eve.      从分析init.rc来看.

Android 遥控车

- CasparZ - LinuxTOY
您确定您真的会用 Android 手机玩赛车. 16 岁的法国学生 Jonathan Rico 使用 Android 手机通过蓝牙实现了对改装玩具汽车的遥控. 操控的方式和那些标榜的智能手机游戏一样,使用重力感应,差别是这次控制的是现实世界中的遥控汽车. 收藏到 del.icio.us |.

Android免费?毛

- Ruby - FeedzShare
来自: 36氪 - FeedzShare  . 发布时间:2011年08月17日,  已有 2 人推荐. 微软CEO Steve Ballmer在预测竞争对手产品时通常口无遮拦. 比如他去年抨击Google的Android战略时,很多人都不屑一顾. 接着Android蚕食了微软的地盘,后来又开始侵犯苹果的地盘.

GetEd2k (Android应用)

- 某牢 - eMule Fans 电骡爱好者
GetEd2k是一个Android应用程序,作者是anacletus. 此应用可以帮助你把网页中的电驴(eDonkey) 链接添加到你个人电脑的电驴客户端里,不过前提是你的客户端开启了用于远程控制的Web interface(Web服务器,网页接口,Web界面),当然,eMule(电骡), MLDonkey 和 aMule 都支持该功能,所以这三种主流电驴客户端的用户都可以使用GetEd2k.

Android 4.0发布

- coofucoo - Solidot
Shawn the R0ck 写道 "2011年10月19日早上10点,谷歌与三星联手在香港发布了Android 4.0和Galaxy Nexus. " Android 4.0 的主要特性包括:更精细的UI,加强多任务和通知功能,锁屏下可打开摄像头和浏览通知,改进文本输入和拼写检查;增强视频录制和图像编辑功能,支持剪裁和旋转图片、消除红眼、添加效果等;面部识别解锁;Android Beam允许两台支持NFC的设备之间交换应用程序、联系人、音乐和视频;Wi-Fi Direct,蓝牙HDP,等等.

NoScript For Android发布

- John - Solidot
用于屏蔽脚本的浏览器流行扩展NoScript发布了Android版本. 开发者称已经在Firefox for Android测试过,此外也应该能工作在基于Maemo的设备上. 移动版NoScript可以帮助移动用户抵抗基于脚本的攻击. Android平台上的扩展功能和桌面版相似,允许用户对每个网站单独设置脚本执行许可.

Android入门:ContentProvider

- - ITeye博客
一、ContentProvider介绍. ContentProvider翻译为“内容提供者”;. 定义:指该应用包含一些方法,供外界访问,其他应用程序可以调用该方法,比如如果应用A创建了一个数据库“test.db”,默认是私有的,即其他应用程序不能对其进行操作,但是如果应用A使用了ContentProvider,则其他应用程序可以访问该数据库;.