课前预习
在了解启动流程之前先了解一下下面两个概念:
1、子进程与父进程的区别
1.除了文件锁以外,其他的锁都会被继承
2.各自的进程ID和父进程ID不同
3.子进程的未决告警被清除
4.子进程的未决信号集设置为空集
2、什么是写时拷贝(copy-on-write)
Linux 的 fork() 使用是通过「写时拷贝(copy-on-write)」 实现。写时拷贝是-种可以推迟甚至避免拷贝数据的技术。
内核此时并不复制整个进程的地址空间,而是让父子进程共享同址空间,从而使各个进行拥有各自的地址空间。
也就是说,资源的复制是在需要写入的时候才会进行,在此之前只有以只读方式共享。
3、Zygote是什么
在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫"init"的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。
Zygote是一个虚拟机进程,同时也是一个虚拟机实例的孵化器,每当系统要求执行一个Android应用程序,Zygote就会fork(分裂)出一个子进程来执行该应用程序。
4、SystemServer是什么
system server 也就是 SystemServer。SystemServer也是一个进程,包括ActivityTaskManagerService、ActivityManagerService、PackageManagerService、WindowManagerService等92种服务。
Android Framework里面两大非常重要的进程:
SystemServer进程。
Zygote进程。
5、Launcher是什么
在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。
当然也可以在 其他应用 启动应用。但是本质上都是调用startActivity()。
系统启动流程解析
1、你了解Android启动流程吗?
当按电源键触发开机:
1.首先会从 ROM 中预定义的地方加载引导程序 「BootLoader」 到 RAM 中,并执行 BootLoader 程序启动 「Linux Kernel」。
2.然后启动用户级别的第一个进程 「init 进程」。init 进 程会解析init.rc 脚 本 做一些初始化工作,包括挂载文件系统、创建工作目录以及启动系统服务进程等,其中系统服务进程包括 「Zygote」、service manager、media 等 。
3.在 「Zygote」 中会进一步去启动 「system_server」 进程,然后在 system_server 进程中会启动 AMS、ATMS、WMS、PMS 等服务,等这些服 务启动之后,ATMS 就会打开 Launcher 应用(他也是个进程)的 homeActivity,
4.最终就看到了手机的「桌面」。
2、system_server 为什么要在 Zygote 进程启动,而不是直接由init启动?
Zygote 作为一个孵化器,可以提前加载一些资源,这样 fork() 时基于 Copy-On-Write 机制创建的其他进程就能直接使用这些资源,而不用重新加载。 比如 system_server 就可以直接使用 Zygote 中的 JNI 函数、共享库、常用的类、以及主题资源。
3、为什么要专门使用 Zygote 进程去孵化应用进程,而不是通过 system_server 呢?
1.system_server 相比 Zygote 多运行了 AMS、WMS 等服务,这些对一个应用程序来说是不需要的。
2.进程的 fork() 对多线程不友好(为了多线程的同步及互斥,会有锁,在fork时,这些锁会一同fork到子进程中),仅会将发起调用的线程拷贝到子进程,这可能会导致死锁,而system_server 中肯定是有很多线程的。
4、在什么情况下会导致死锁?
在 POSIX 标准中,fork 的行为是这样的:复制整个用户空间的数据(通常使用 copy-on-write 的策略,所以可以实现的速度很快)以及所有系统对象,然后仅复制当前线程到子进程。
「注:所有父进程中别的线程,到了子进程中都是突然蒸发掉的」
对于锁来说,从 OS 看,每个锁有一个所有者,即最后一次 lock 它的线程。假设这么一个环境,在 fork 之前,有一个子线程 lock 了某个锁,获得了对锁的所有权。fork 以后,在子进程中,所有的额外线程都人间蒸发了。而锁却被正常复制了,在子进程看来,这个锁没有主人,所以没有任何人可以对它解锁。当子进程想 lock 这个锁时,就没办法解开这个锁,程序就必然发生死锁。
5、Zygote 为什么不采用 Binder 机制进行 IPC 通信?
Binder 机制中存在 Binder 线程池,是多线程的。如果 Zygote 采用 Binder 的话就存在上面说的fork() 与多线程的问题了。
其实严格来说,Binder 机制不一定要多线程,所谓的 Binder 线程只不过是在循环读取 Binder 驱动的消息而已,只注册一个 Binder 线程也是可以工作的,比如 service manager就是这样的。
实际上 Zygote 尽管没有采取 Binder 机制,它也不是单线程的,但它在 fork() 前主动停止了其他线程,fork() 后重新启动了。
相关推荐
Android 启动流程