IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 重学Android之Framework层应用程序进程创建流程 -> 正文阅读

[移动开发]重学Android之Framework层应用程序进程创建流程

Android系统启动完成后,会启动第一Android应用Launcher。之后在用户操作下启动其他的应用程序。这两个流程大体一致,本文主要分析启动Launcher的启动流程。

Android系统源码版本:9.0.0_r3

整体流程图如下:

Zygote启动及应用进程创建流程

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_process32app_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相关函数。代码如下:

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中查找到要启动程序的信息,将要启动程序的信息通过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        }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:48:38  更:2021-08-23 16:49:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:43:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码