本文主要是介绍重学Android之Framework层应用程序进程创建流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android系统启动完成后,会启动第一Android应用Launcher。之后在用户操作下启动其他的应用程序。这两个流程大体一致,本文主要分析启动Launcher的启动流程。
Android系统源码版本:9.0.0_r3
整体流程图如下:
Zygote启动流程
Android Kernel启动后启动第一个进程init,init将解析init.*.rc文件启动进程zygote。
/system/core/rootdir/init.zygote32_64.rc
1 service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
2 class main
3 priority -20
4 user root
5 group root readproc reserved_disk
6 socket zygote stream 660 root system
7 onrestart write /sys/android_power/request_state wake
8 onrestart write /sys/power/state on
9 onrestart restart audioserver
10 onrestart restart cameraserver
11 onrestart restart media
12 onrestart restart netd
13 onrestart restart wificond
14 writepid /dev/cpuset/foreground/tasks
15
16 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
17 class main
18 priority -20
19 user root
20 group root readproc reserved_disk
21 socket zygote_secondary stream 660 root system
22 onrestart restart zygote
23 writepid /dev/cpuset/foreground/tasks
init启动的程序app_process32或app_process64 跟--zygote
参数表明启动的是zygote进程。这里的app_process32
、app_process64
表示32位zygote进程和64位zygote进程,用于兼容包含so库为32位的应用启动。其实在Android环境中我们是可以用app_proccess*去运行一个Dalvik格式的java字节码文件,就像在台式机上用java运行字节码一样。
zygote启动之后将完成ART虚拟机的创建工作并运行com.android.internal.os.ZygoteInit。关键内容如下所示
/frameworks/base/cmds/app_process/app_main.cpp
349 if (zygote) {
350 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
351 } else if (className) {
352 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
353 } else {
354 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
355 app_usage();
356 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
357 }
在com.android.internal.os.ZygoteInit中会完成Android环境中Framework关键Java类文件的加载工作。创建本地套接字用ZygoteServer管理,通过fork调用创建子进程system_server进程。开启本地套接字ZygoteServer的监听功能即运行runSelectLoop方法监听是否有新套接字或读写事件发生。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
750 public static void main(String argv[]) {
751 ZygoteServer zygoteServer = new ZygoteServer();
752//.....删除不相干代码
832 if (startSystemServer) {
833 Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
834
835 // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
836 // child (system_server) process.
837 if (r != null) {
838 r.run();
839 return;
840 }
841 }
842
843 Log.i(TAG, "Accepting command socket connections");
844
845 // The select loop returns early in the child process after a fork and
846 // loops forever in the zygote.
847 caller = zygoteServer.runSelectLoop(abiList);
848 } catch (Throwable ex) {
849 Log.e(TAG, "System zygote died with exception", ex);
850 throw ex;
851 } finally {
852 zygoteServer.closeServerSocket();
853 }
854
855 // We're in the child process and have exited the select loop. Proceed to execute the
856 // command.
857 if (caller != null) {
858 caller.run();
859 }
860 }
在这里本地套接字即UDS(Unix Domain Socket),其实就是一种进程间通信方式,像Nginx,MySQL中都UDS用来做进程间通信。Android进程间通信方式比Linux多了Binder这种进程间通信方式。本文不会详细讲解Binder,只要知道Binder其实就是用于两个不同进程间通信即可,跟管道、信号量、UDS没有本质的不同。
system_server进程启动流程
system_server进程将调用com.android.server.SystemServer,SystemnServer将启动各个重要的服务,代码如下
/frameworks/base/services/java/com/android/server/SystemServer.java
// Start services.
427 try {
428 traceBeginAndSlog("StartServices");
429 startBootstrapServices();
430 startCoreServices();
431 startOtherServices();
432 SystemServerInitThreadPool.shutdown();
433 } catch (Throwable ex) {
434 Slog.e("System", "******************************************");
435 Slog.e("System", "************ Failure starting system services", ex);
436 throw ex;
437 } finally {
438 traceEnd();
439 }
启动的服务有ActivityManagerService、WindowManagerService、PackageManagerService、InputManagerService、BluetoothManagerService等服务类。
其中PackageManagerService将完成对手机上已安装的应用程序的解析,如解析Apk安装位置、Manifest信息,资源文件、类文件路径等。
system_server启动完毕后调用AMS的systemReady方法,发送启动Launcher的Intent,PMS将找到Launcher的安装路径,调用AMS的startProcess。startProcess经过一系列调用最终使用UDS与zygote进程通信,发送相应的命令,让zygote创建子进程。AMS将返回的子进程pid和与之关联app信息放入mPidsSelfLocked成员变量中。代码如下
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
4530 private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
4531 long expectedStartSeq, boolean procAttached) {
4532 //省略很多代码....
4598 synchronized (mPidsSelfLocked) {
4599 this.mPidsSelfLocked.put(pid, app);
4600 if (!procAttached) {
4601 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
4602 msg.obj = app;
4603 mHandler.sendMessageDelayed(msg, usingWrapper
4604 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
4605 }
4606 }
4607 checkTime(app.startTime, "startProcess: done updating pids map");
4608 return true;
4609 }
应用进程启动流程
在这里ZygoteServer的本地套接字监听到有消息到来时将fork一个新的子进程,这新的子进程就继承了zygote进程的资源如已经创建好的ART虚拟机,这样能够加快应用的创建启动。
关键代码如下
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
123 Runnable processOneCommand(ZygoteServer zygoteServer) {
124 String args[];
125 Arguments parsedArgs = null;
126 FileDescriptor[] descriptors;
127
128 try {
129 args = readArgumentList();
130 descriptors = mSocket.getAncillaryFileDescriptors();
131 } catch (IOException ex) {
132 throw new IllegalStateException("IOException on command socket", ex);
133 }
134//删除不相关代码...
146 parsedArgs = new Arguments(args);
147
148
231
232 fd = null;
233
234 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
235 parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
236 parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
237 parsedArgs.instructionSet, parsedArgs.appDataDir);//删除不相关代码...
238
240 if (pid == 0) {
241 // in child
242 zygoteServer.setForkChild();
243
244 zygoteServer.closeServerSocket();
245 IoUtils.closeQuietly(serverPipeFd);
246 serverPipeFd = null;
247
248 return handleChildProc(parsedArgs, descriptors, childPipeFd,
249 parsedArgs.startChildZygote);
250 } else {
251 // In the parent. A pid < 0 indicates a failure and will be handled in
252 // handleParentProc.
253 IoUtils.closeQuietly(childPipeFd);
254 childPipeFd = null;
255 handleParentProc(pid, descriptors, serverPipeFd);
256 return null;
257 }
258
262 }
在子进程中将解析其他进程(system_server)发过来的参数,运行指定的类。通常这个类就是ActivityThread,这个子进程就是我们新启动的应用进程,当前这个进程还不知道要到哪里去加载应用程序对应字节码和资源文件。当ActivityThread启动后将与system_server 进行进程间通信(Binder),调用AMS相关函数。代码如下:
/frameworks/base/core/java/android/app/ActivityThread.java
6478 private void attach(boolean system, long startSeq) {
6479 sCurrentActivityThread = this;
6480 mSystemThread = system;
6481 if (!system) {
6482 ViewRootImpl.addFirstDrawHandler(new Runnable() {
6483 @Override
6484 public void run() {
6485 ensureJitEnabled();
6486 }
6487 });
6488 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
6489 UserHandle.myUserId());
6490 RuntimeInit.setApplicationObject(mAppThread.asBinder());
6491 final IActivityManager mgr = ActivityManager.getService();
6492 try {
6493 mgr.attachApplication(mAppThread, startSeq);
6494 } catch (RemoteException ex) {
6495 throw ex.rethrowFromSystemServer();
6496 }
在6493行 ActivityThread调用mgr.attachApplication,由于Binder机制将调用AMS的attachApplication方法。
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
7932 public final void attachApplication(IApplicationThread thread, long startSeq) {
7933 synchronized (this) {
7934 int callingPid = Binder.getCallingPid();
7935 final int callingUid = Binder.getCallingUid();
7936 final long origId = Binder.clearCallingIdentity();
7937 attachApplicationLocked(thread, callingPid, callingUid, startSeq);
7938 Binder.restoreCallingIdentity(origId);
7939 }
7940 }
attachApplication方法中将获取正在启动进程的pid,通过pid在mPidsSelfLocked(或者通过startSeq在mPendingStarts)中查找到要启动程序的信息,将要启动程序的信息通过Binder进程间通信(即IApplicationThread相关方法)发送给应用进程,由应用进程去加载相应的类。
应用进程加载完成后告知AMS,AMS将控制应用进程启动Activity,此后AMS下达命令,应用进程执行,执行完成后告知AMS。应用进程就像一个提线木偶一样受到AMS的制约。(现在的插件化技术,就是Hook掉对应的接口,欺骗AMS完成插件中四大组件的加载,即常说的欺上瞒下)
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
7573 int pid, int callingUid, long startSeq) {
7574
7575 // Find the application record that is being attached... either via
7576 // the pid if we are running in multiple processes, or just pull the
7577 // next app record if we are emulating process with anonymous threads.
7578 ProcessRecord app;
7579 long startTime = SystemClock.uptimeMillis();
7580 if (pid != MY_PID && pid >= 0) {
7581 synchronized (mPidsSelfLocked) {
7582 app = mPidsSelfLocked.get(pid);
7583 }
7584 } else {
7585 app = null;
7586 }
7587
7588 // It's possible that process called attachApplication before we got a chance to
7589 // update the internal state.
7590 if (app == null && startSeq > 0) {
7591 final ProcessRecord pending = mPendingStarts.get(startSeq);
7592 if (pending != null && pending.startUid == callingUid
7593 && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
7594 startSeq, true)) {
7595 app = pending;
7596 }
7597 }
7598
7599 if (app == null) {
7600 Slog.w(TAG, "No pending application record for pid " + pid
7601 + " (IApplicationThread " + thread + "); dropping process");
7602 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
7603 if (pid > 0 && pid != MY_PID) {
7604 killProcessQuiet(pid);
7605 //TODO: killProcessGroup(app.info.uid, pid);
7606 } else {
7607 try {
7608 thread.scheduleExit();
7609 } catch (Exception e) {
7610 // Ignore exceptions.
7611 }
7612 }
7613 return false;
7614 }
总结
Android启动过程中init进程创建zygote进程,zygote进程创建system_server进程作为系统的核心服务进程,同时创建本UDS服务端监听请求的到来。每当需要创建普通应用进程时,通过UDS与zygote进程通信,由zygote进程fork出新的应用进程。这样做的好处是,zygote进程中ART已经创建好,能很快创建好进程需要的环境。
整个Android系统是由多个服务进程组成,如zygote、system_server、 servicemanager、surfaceflinger(在Android2.3版本及之前surfaceflinger在system_server进程中创建,不是独立进程)等。各个服务进程间通过binder机制进行进程间通信,协调各个应用程序有序的使用系统资源。
如屏幕要绘制的图形的都会交给surfaceflinger去完成渲染。可以想象如果每一个程序都能独立往屏幕上绘制图形,这么多程序一起绘制,屏幕显示将会一团糟。
有些服务进程(如surfaceflinger)对应的程序完全由C++实现,不包含Java代码,就不需要创建ART环境,这类服务通常都是独立启动。包含Java代码的进程(如system_server、com.android.systemui、大多数普通应用程序等)通常使用zygote通过fork创建。
这篇关于重学Android之Framework层应用程序进程创建流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!