parent
16cec8ca89
commit
42e3500b4f
@ -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…
Reference in new issue