说说Android应用程序的进程启动

一、进程启动方式

在Android系统启动的时候,一些核心进程是由init进程fork出来,比如media、SurfaceFlinger、Zygote等,而另外一些系统核心服务进程则是由Zygote进程fork出来,比如我们的SystemServer进程,在这里面启动AMS,PMS等。那么对于进程的启动方式fork有哪几种方式?

一般情况下分为两种,fork 带execve和不带execve,有什么 区别?如果是不带execve那么沿用的是父进程的资源。如果是带了execve则重新向系统申请资源。

因此,Android系统中有很多个应用,当这些应用程序进程需要启动的时候需要使用fork execve的方式,也就是说每个应用程序进程都需要自己向Android系统申请独立的资源。

二、应用程序进程启动的原理

在Android系统中,实际上我们是找不到启动进程的接口,对于应用程序来讲,进程的启动是被动的,即在Framework中,当某个组件需要启动的时候,系统会对该组件所依赖的进程进行检测,查看该进程是否已经启动通过getProcessRecordLocked函数来检测,如果已经 启动,则启动真的组件然后返回,否则通过调用AMS中的startProcessLocked(porcessName)来启动进程。伪代码块如下:

在com.android.server.am.ActivityStackSupervisor.java中
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);

        //app.thread为应用的AMS binder句柄,实际上AMS也会持有一个应用的binder句柄,构成一个双向调用,因为有时候应用需要应用与AMS进行通信。这个双向句柄是由应用启动的时候向AMS打报告并注册生成
        if (app != null && app.thread != null) {
            //启动组件
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        }
        
        //启动进程,实际上是调用AMS中的
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

由于SystemServer进程也会有Loop循环,处理自己的消息,当AMS需要启动应用程序进程的时候,则向SystemService发送消息,具体是在AMS的handleProcessStartedLocked函数中进行,代码如下:

private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
            long expectedStartSeq, boolean procAttached) {
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                
                //发送消息,由SystemServer进程的Loop循环处理消息,执行runOnce函数,进而启动对应的入口函数main,这里是ActivityThread.main()
                mHandler.sendMessageDelayed(msg, usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
        }
        return true;
    }

在android.app.ActivityThread.java中的main函数核心代码如下,从这里我们可以得知App中Application中的onAttachBaseContext方法是在什么时候被调用起来的。

public static void main(String[] args) {
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        
        //获取AMS的Binder对象,向AMS报告,说明应用程序已经启动好
        //IActivityManager mgr = ActivityManager.getService();
        //mgr.attachApplication(mAppThread, startSeq);
        //实际上就是我们App中Application的onAttachBaseContext方法被调用
        thread.attach(false);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

这也就是为什么有多少个子进程,Application中的生命周期会被调用多少次的原因。

当某个组件启动的时候,会从一个进程Record中获取该进程,如果获取不到则说明进程没有启动,即ApplicationInfo对象为null,如果获取到ApplicationInfo.thread为null,说明该进程启动后还没有向AMS打报告注册,此时进程向AMS注册。否则开始AMS的startProcessLock函数启动进程,如上代码块说明。

实际上一个应用程序进程的启动就是遵循Android的进程启动时的Loop机制,通过Zygote进程fork出来,在ZygoteConnnection中的runOnce()函数中走下去,最终调用到ActivityThread的main入口函数,进程启动。

发布了11 篇原创文章 · 获赞 3 · 访问量 776

猜你喜欢

转载自blog.csdn.net/xj_hnust/article/details/97524471