add some files

master
Omooo 5 years ago
parent 16cec8ca89
commit 42e3500b4f
  1. 163
      blogs/Android/Framework/Android 系统的启动流程.md
  2. 23
      blogs/Android/Framework/Choreographer.md
  3. 139
      blogs/Android/Framework/Zygote 的理解.md
  4. 12
      blogs/Android/Framework/深入理解 Android 内核设计思想/SurfaceFlinger.md
  5. 127
      blogs/Android/Framework/添加系统服务.md

@ -0,0 +1,163 @@
---
Android 系统的启动流程
---
#### Android 有哪些主要的系统进程?
在 init.rc 启动配置文件中定义了很多 Service,这些 Service 就是要单独启动的系统服务进程。
```ini
service zygote /system/bin/app_process ...
service servicemanager /system/bin/servicemanager ...
service surfaceflinger /system/bin/surfaceflinger ...
service media /system/bin/mediaserver ...
...
```
#### 这些系统进程是怎么启动的?以及做了什么事?
Zygote 启动:
1. init 进程 fork 出 zygote 进程
2. 启动虚拟机,注册 jni 函数,为进入 Java 世界做准备
3. 预加载系统资源
4. 启动 SystemServer
5. 进入 Socket Loop
Zygote 工作流程就是执行 runOnce 函数的过程。
SystemServer 启动:
```java
private static boolean startSystemServer(...) {
String args[] = {
...
"com.android.server.SystemServer",
}
int pid = Zygote.forkSystemServer(...);
if(pid == 0){
handlerSystemServerProcess(parsedArgs);
}
return true;
}
```
```java
void handlerSystemServerProcess(Arguments parsedArgs) {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, ...);
}
```
```java
void zygoteInit(String[] argv, ...) {
commonInit();
nativeZygoteInit();
applicationInit(argv, ...);
}
```
```java
// 启动 Binder 机制
void nativeZygoteInit() {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
```
```java
// 执行 SystemServer 的 main 函数
void applicationInit() {
invokeStaticMain(args, ...);
}
```
```java
public static void main() {
new SystemServer().run();
}
```
```java
// SystemServer#run
```
```java
private void run() {
Looper.prepareMainLooper();
System.loadLibrary("android_servers");
createSystemContext();
startBootstrapServcies();
startCoreServices();
startOtherServices();
Looper.loop();
}
```
#### 两个问题:
1. 系统服务是怎么启动的?
2. 怎么解决系统服务之间的相互依赖?
第一个问题,系统服务是怎么启动的?
我们只需要关注两个问题:
1. 系统服务怎么发布,让应用程序可见?
```java
void publishBinderService(String name, IBiner service, ...) {
ServiceManager.addService(name, service, allowlsolated);
}
```
也就是把系统服务的 Binder 注册到 ServiceManager 中。
2. 系统服务跑在什么线程?
3.
课堂作业:
1. 为什么系统服务不都跑在 binder 线程里呢?
2. 为什么系统服务不都跑在自己私有的工作线程里呢?
3. 跑在 binder 线程和跑在工作线程,如何取舍?
第二个问题,怎么解决系统服务之间的相互依赖?
1. 分批启动(AMS、PMS、PKMS)
2. 分阶段启动(阶段1、阶段2...)
#### 桌面启动
在 AMS 服务就绪的时候,会调用以下函数:
```java
public void systemReady(final Runnable goingCallback) {
//...
startHomeActivityLocked(mCurrentUserId, "systemReady");
}
```
在 Launcher2 Activity 的 onCreate 里面会启动一个 LoaderTask:
```java
mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
```
这个 LoaderTask 会向 PMS 去查询已经安装的应用:
```
mPm.queryIntentActivitiesAsUser
```
#### 说说 Android 系统的启动流程?
1. Zygote 是怎么启动的?
2. systemServer 是怎么启动的?
3. 系统服务是怎么启动的?

@ -0,0 +1,23 @@
---
Choreographer
---
#### 概述
Choreographer 是用来控制同步处理输入(Input)、动画(Animation)、绘制(Draw)三个操作(UI 显示的时候每一帧要完成的事情只有这三种)。其内部维护着一个 Queue,使用者可以通过 postXxx 来把一系列待运行的 UI 操作放到 Queue 中。这些事件会在 Choreographer 接收 VSYNC 信号后执行这些操作,比如 ViewRootImpl 对于 ViewTree 的更新事件:
```java
// ViewRootImpl
void scheduleTraversals() {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
```
#### 对 Vsync 信号的监听
#### 参考
[Choreographer工作逻辑总结](https://github.com/SusionSuc/AdvancedAndroid/blob/master/Rabbit%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90/Choreographer%E5%B7%A5%E4%BD%9C%E9%80%BB%E8%BE%91%E6%80%BB%E7%BB%93.md)

@ -0,0 +1,139 @@
---
谈谈你对 Zygote 的理解?
---
#### 了解 Zygote 的作用
1. 启动 SystemServer
2. 孵化应用进程
#### 熟悉 Zygote 的启动流程
启动三段式:
进程启动 -> 准备工作 -> LOOP
Zygote 的启动可以分为两块:
1. 进程是怎么启动的?
2. 进程启动之后做了什么?
第一个问题:进程是怎么启动的?
Init 进程是 Linux 启动之后,用户空间的第一个进程。加载了一个 init.rc 配置文件,里面配置了很多系统服务。通过 fork+execev 系统调用。
```ini
// Service Name: zygote, 可执行路径 + 参数
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
```
启动进程有两种方式:
第一种是 fork + handle:
```c
pid_t pid = fork();
if(pid == 0){
// child process
} else {
// parent process
}
```
第二种是 fork + execve:
```c
pid_t pid = fork();
if(pid == 0){
// child process
execve(path, argv, env);
} else {
// parent process
}
```
调用 fork 函数创建子进程,它会返回两次,子进程返回的 pid == 0,父进程返回的 pid 等于子进程的 pid。
默认情况下,子进程继承了父进程创建的所有资源,如果调用了系统调用 execve 去加载另一个二进程程序的话,那么继承父进程的资源就会被清掉。
信号处理,SIGCHLD 信号:
父进程 fork 出了子进程,如果子进程挂了,那么它的父进程就会收到 SIGCHLD 信号,然后就可以重启。
第二个问题:Zygote 进程启动之后做了什么?
* Zygote 的 Native 世界
* Zygote 的 Java 世界
Native 世界其实就是为了进入 Java 世界做准备,有以下三件事:
1. 启动虚拟机
2. 注册 Android 的 JNI 函数
3. 进入 Java 世界
```c
int main(int argc, char *argv[]) {
JavaVM *jvm;
JNIEnv *env;
// 1
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
// 2
jclass clazz = env->FindClass("ZygoteInit");
jmethodID method = env->GetStaticMethodID(clazz, "Main", "(Ljava/lang/String;)V");
env->CallStaticVoidMethod(clazz, method, args);
jvm->DestoryJavaVM();
}
```
Java 虚拟机在 Zygote 都已经创建好了,应用程序都是由 Zygote 创建而来的,就直接继承了它的虚拟机。
再来看一下 Zygote 的世界,做了以下事情:
1. 通过 registerServerSockert 方法来创建一个 Server 端的 Socket,这个 name 为 zygote 的 socket 用于等待 AMS 请求 Zygote 来创建新的应用程序进程
2. 预加载资源,Preload Resources,在 Zygote 进程预加载系统资源后,然后通过它孵化出其他的虚拟机进程,进而共享虚拟机内存和框架层资源,这样大幅度提高应用程序的启动和运行速度
3. 启动 System Server
4. 进入 Loop 循环,执行 runSelectLoop 方法等待消息去创建应用进程
Zygote 处理请求的关键代码:
```java
boolean runOnce() {
// 1. 读取参数列表
String[] args = readArgumentList();
// 2. 启动子进程
int pid = Zygote.forkAndSpecialize();
if(pid == 0){
// 3. 在进程里面干活,其实就是执行了一个 java 类的 main 函数,java 类名就是上面读取的参数列表,参数列表是 AMS 跨进程发过来的,类名其实就是 ActivityThread
// in child
handleChildProc(args, ...);
return true;
}
}
```
注意细节:
1. Zygote 在 fork 的时候要保证是单线程的,为了避免造成死锁和状态不一致等问题
2. Zygote 的 IPC 没有采用 Binder,而是本地 Socket
问题:
1. 孵化应用进程这种事为什么不交给 SystemServer 来做,而专门设计一个 Zygote ?
> 我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类资源系统等等,这些都是非常耗时的,如果能在 zygote 里就给这些必要的初始化工作做好,子进程在 fork 的时候就能直接共享,那么这样的话效率就会非常高。这个就是 zygote 存在的价值,这一点 SystemServer 是替代不了的,主要是因为 SystemServer 里跑了一堆系统服务,这些是不能继承到应用程序的。而且我们应用程序在启动的时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一些乱七八糟的东西,所以呢,不如给 SystemServer 和应用进程里都要用到的资源抽出来单独放到一个进程里,也就是这个 zygote 进程,然后 zygote 进程在分别孵化出 SystemServer 进程和应用进程。孵化出来之后,SystemServer 进程和应用程序进程就可以各干各事了。
1. Zygote 的 IPC 通信机制为什么不采用 Binder?如果采用 Binder 的话会有什么问题呢?
> https://www.zhihu.com/question/312480380
>
> https://blog.csdn.net/qq_39037047/article/details/88066589
#### 深刻理解 Zygote 的工作原理

@ -0,0 +1,12 @@
---
SurfaceFlinger
---
#### 概述
SurfaceFlinger 是负责绘制应用 UI 的核心,从名字上可以看出其功能是将所有的 Surface 合成工作。不论使用什么渲染 API,所有的东西最终都是渲染到 Surface 上,Surface 代表 BufferQueue 的生产者端,并且由 SurfaceFlinger 消费。Android 平台所创建的 Window 都由 Surface 所支持,所有可见的 Surface 渲染到显示设备都是通过 SurfaceFlinger来完成的。
SurfaceFlinger 进程是由 init 进程创建的,运行在独立的 SurfaceFlinger 进程。Android 应用程序必须跟 SurfaceFlinger 进程交互,才能完成将应用 UI 绘制到 FrameBuffer(帧缓冲区)。这个交互便涉及到进程间的通信,采用 Binder IPC 方式,名为 "SurfaceFlinger" 的 Binder 服务端运行在 SurfaceFlinger 进程。

@ -0,0 +1,127 @@
---
怎么添加一个系统服务?
---
1. 了解如何使用系统服务?
2. 了解系统服务调用的基本原理
3. 了解服务的注册原理
#### 如何使用系统服务以及基本原理
```java
// ContextImpl
public Object getSystemServer(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
// SystemServiceRegistry
SYSTEM_SERVICE_FETCHERS = new ArrayMap<String, ServiceFetcher<?>>();
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
// 具体实现
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
T service = (T) cache[mCacheIndex];
if (service != null) {
return service;
} else {
service = createService(ctx);
cache[mCacheIndex] = service;
}
}
```
然后看一下 createService 是如何实现的,这里以 Power Service 为例:
```java
registerService(Context.POWER_SERVICE, PowerManager.class, new CachedServiceFetcher<PowerManager>()) {
@Override
public PowerManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler());
}
}
```
```java
// ServiceManager#getService
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
```
#### 服务的注册原理
```java
public static void addService(String name, IBinder service) {
getIServiceManager().addService(name, service, false);
}
```
什么时候注册的系统服务?
就是在 SystemServer 启动时注册。它的主要流程是:启用 binder 机制 -> 启动各类系统服务 -> 进去 Loop 循环。
需要注意的是,并不是所有的系统服务都是在 SystemServer 进程里的,有一些服务·是单开一个进程的,比如 ServiceManager、SurfaceFlinger、MediaService 等,但是同样需要注册到 ServiceManager 中。
独立进程的系统服务实现,以 SurfaceFlinger 为例:
```ini
service surfaceflinger /system/bin/surfaceflinger
class core
user system
group graphics drmrpc
onrestart restart zygote
writepid /dev/cpuset/system-background/tasks
```
```c
int main(int, char**) {
sp<ProcessState> ps(ProcessState::self());
// 启动 binder 线程池
ps->startThreadPool();
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
flinger->init();
// 注册 SurfaceFlinger 服务
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(serviceName, flinger, false);
flinger->run();
return 0;
}
```
ProcessState 是一个进程内的单例,它的构造函数里面会启动 binder 机制,包括打开 binder 驱动,映射内存,分配缓冲区等等。
最后看一下defaultServiceManager 函数:
```c
sp<IServiceManager> defaultServiceManager() {
if(gDefaultServiceManager != null) {
return gDefaultServiceManager;
}
while(gDefaultServiceManager == null) {
gDefaultServiceManager = getContextObject();
if(gDefaultServiceManager==null) sleep(1);
}
}
```
因为 ServiceManager 和 SurfaceFlinger 都是由 init 进程启动的,所以这里如果是独立线程启动,可能在注册服务时,ServiceManager 还未来得及向 binder 驱动注册,所以如果拿不到 ServiceManager 就睡眠不停循环获取。
Loading…
Cancel
Save