android系统启动简单流程分析
主要流程大概就是boot rom ->boot loader->kernel->init->zygote->system server->launcher app
当用户按下开机键时候,会引导rom,加载bootloader到内存中去,开始拉起linux os,当linux启动完成后,kernel寻找init.rc文件并启动,在高版本中init.rc会进行拆分,有32位还有64位的zygote。
启动init会进入system/core/init/init.cpp文件的main方法,总结init方法干了啥基本就是
(1)创建和挂载启动所需要的文件和目录
(2)初始化和启动属性服务。
(3)解析init.rc配置文件,并且启动了Zygote进程
Zygote
这边可以看是通过androidRuntime启动的
andriodRuntime是啥
显而易见,就是为Android应用运行所需的运行时环境
Dalvik VM: Android的Java VM, 解释运行Dex格式Java程序。每个进程运行一个虚拟机(什么
叫运行虚拟机?说白了,就是一些C代码,不停的去解释Dex格式的二进制码(Bytecode),把
它们转成机器码(Machine code),然后执行,当然,现在大多数的Java 虚拟机都支持JIT,也
就是说,bytecode可能在运行前就已经被转换成机器码,从而大大提高了性能。过去一个普
遍的认识是Java 程序比C,C++等静态编译的语言慢,但随着JIT的介入和发展,这个已经完全
是过去时了,JIT的动态性运行允许虚拟机根据运行时环境,优化机器码的生成,在某些情况
下,Java甚至可以比C/C++跑得更快,同时又兼具平台无关的特性,这也是为什么Java如今如
此流行的原因之一吧)。
Android的Java 类库, 大部分来自于 Apache Hamony, 开源的Java API 实现,如 java.lang,
java.util, java.net. 但去除了AWT, Swing 等部件。
JNI: C和Java互调的接口。
Libc: Android也有很多C代码,自然少不了libc,注意的是,Android的libc叫 bionic C(抄来的)
他干了啥
创建虚拟机和一些对应的映射表,最重要的可能是
//通过JNI调用ZygoteInit的main方法env->CallStaticVoidMethod(startClass,startMeth,strArray);接下来看zygoteinit方法
ZygoteInit
不截图了主要做了
new ZygoteServer(); //新建Zygote服务器端
registerServerSocketFromEnv(socketName);//注册Socket
preloadClasses();/加载指定的类到内存并且初始化
preloadResources//加载Android通用的资源,比如drawable、color...
preloadOpenGL();//加载OpenGL
preloadSharedLibraries()//加载共用的Library
preloadTextResources() //加载Text资源,字体等
Zygote.forkSystemServer//fork systemserver
并通过runSelectLoop方法等待AMS的请求来创建新的应用程序进程
然后就是launcher界面咧
fork
使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信息)。
除了文件锁之外,其他锁都会被继承
写时copy
内核并不复制整个进程的地址空间,而是让父子进程共享一个地址空间,只用在需要写入的时候才会复制地址空间,从而使各自都有各自的地址空间,资源的复制实在需要写入的时候进行,在此之前,只有以只读方式共享
孤儿进程僵尸进程
父子进程交替执行,如果爸爸退出了,儿子还没退出,那么爸爸进程变成init进程。如果儿子先走,爸爸还没退出,那么儿子必须等到爸爸知道儿子退出才能真的结束,不然儿子就变成僵进程
多进程的fork调用
复制整个用户空间的数据以及所有系统对象,但只复制当前线程到子线程,爸爸进程里面的其他线程都会消失,所以有一种情况造成死锁,当父进程里面一个子线程lock住了,fork之后,额外线程消失了,锁正常复制,这个锁没有主人了,就没有人可以对他解锁
疑问
为什么system_server要在zygote中启动而不是init直接启动呢,zygote作用孵化器,可以提前加载一些资源,通过fork的时候,其他进程就能使用这些资源不用重新加载,比如一些指定类和通用资源
为什么使用zygote启动进程而不是让systemserver去孵化呢,进程的fork对多线程不友好,fork的时候只会使当前线程fork到子进程中去,可能会导致死锁,而system_server是多线程的
zygote为什么使用socket通信而不是使用binder机制进行ipc通讯,binder机制存在binder的线程池是多线程的,实际上zygote金管没有采取binder机制,他也不是单线程的,但他在fork前主动停止了其他线程,fork后重新启动