相关文章
Android系统架构与系统源码目录
Android系统启动流程(一)解析init进程启动过程
Android系统启动流程(二)解析Zygote进程启动过程
Android系统启动流程(三)解析SyetemServer进程启动过程
Android系统启动流程(四)Launcher启动过程与系统启动流程javascript
在此前我讲过Android系统的启动流程,系统启动后,咱们就比较关心应用程序是如何启动的,这一篇咱们来一块儿学习Android7.0 应用程序进程启动过程,须要注意的是“应用程序进程启动过程”,而不是应用程序启动过程。关于应用程序启动过程,我会在后续系列的文章中讲到。但愿阅读这篇文章前先阅读本文列出的相关文章,要不你一脸蒙蔽,就别怪我了。java
要想启动一个应用程序,首先要保证这个应用程序所须要的应用程序进程已经被启动。ActivityManagerService在启动应用程序时会检查这个应用程序须要的应用程序进程是否存在,不存在就会请求Zygote进程将须要的应用程序进程启动。在Android系统启动流程(二)解析Zygote进程启动过程这篇文章中,我提到了Zygote的Java框架层中,会建立一个Server端的Socket,这个Socket用来等待ActivityManagerService来请求Zygote来建立新的应用程序进程的。咱们知道Zygote进程经过fock自身建立的应用程序进程,这样应用程序程序进程就会得到Zygote进程在启动时建立的虚拟机实例。固然,在应用程序建立过程当中除了获取虚拟机实例,还能够得到Binder线程池和消息循环,这样运行在应用进程中应用程序就能够方便的使用Binder进行进程间通讯以及消息处理机制了。先给出应用程序进程启动过程的时序图,而后对每个步骤进行详细分析,以下图所示。android
ActivityManagerService会经过调用startProcessLocked函数来向Zygote进程发送请求,以下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java数组
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid;//1
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
...
/** * 2 对gids进行建立和赋值 */
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
...
if (entryPoint == null) entryPoint = "android.app.ActivityThread";//3
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
/** * 4 */
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
...
} catch (RuntimeException e) {
...
}
}
...
}复制代码
在注释1处的达到建立应用程序进程的用户ID,在注释2处对用户组ID:gids进行建立和赋值。注释3处若是entryPoint 为null则赋值为"android.app.ActivityThread"。在注释4处调用Process的start函数,将此前获得的应用程序进程用户ID和用户组ID传进去,第一个参数entryPoint咱们得知是"android.app.ActivityThread",后文会再次提到它。接下来咱们来查看Process的start函数,以下所示。
frameworks/base/core/java/android/os/Process.java微信
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
...
}
}复制代码
start函数中只调用了startViaZygote函数:
frameworks/base/core/java/android/os/Process.java架构
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
/** * 1 */
ArrayList<String> argsForZygote = new ArrayList<String>();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
...
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
...
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}复制代码
在注释1处建立了字符串列表argsForZygote ,并将启动应用进程的启动参数保存在argsForZygote中,函数的最后会调用zygoteSendArgsAndGetResult函数,须要注意的是,zygoteSendArgsAndGetResult函数中第一个参数中调用了openZygoteSocketIfNeeded函数,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult函数以下所示。
frameworks/base/core/java/android/os/Process.javaapp
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}复制代码
zygoteSendArgsAndGetResult函数主要作的就是将传入的应用进程的启动参数argsForZygote,写入到ZygoteState中,结合上文咱们知道ZygoteState实际上是由openZygoteSocketIfNeeded函数返回的,那么咱们接着来看openZygoteSocketIfNeeded函数,代码以下所示。
frameworks/base/core/java/android/os/Process.java框架
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//1
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
if (primaryZygoteState.matches(abi)) {//2
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);//3
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);复制代码
在讲到Zygote进程启动过程时咱们得知,在Zygote的main函数中会建立name为“zygote”的Server端Socket。在注释1处会调用ZygoteState的connect函数与名称为ZYGOTE_SOCKET的Socket创建链接,这里ZYGOTE_SOCKET的值为“zygote”。注释2处若是链接name为“zygote”的Socket返回的primaryZygoteState与当前的abi不匹配,则会在注释3处链接name为“zygote_secondary”的Socket。这两个Socket区别就是:name为"zygote”的Socket是运行在64位Zygote进程中的,而name为“zygote_secondary”的Socket则运行在32位Zygote进程中。既然应用程序进程是经过Zygote进程fock产生的,当要链接Zygote中的Socket时,也须要保证位数的一致。socket
Socket进行链接成功并匹配abi后会返回ZygoteState类型对象,咱们在分析zygoteSendArgsAndGetResult函数中讲过,会将应用进程的启动参数argsForZygote写入到ZygoteState中,这样Zygote进程就会收到一个建立新的应用程序进程的请求,咱们回到ZygoteInit的main函数,以下所示。ide
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
try {
...
//注册Zygote用的Socket
registerZygoteSocket(socketName);//1
...
//预加载类和资源
preload();//2
...
if (startSystemServer) {
//启动SystemServer进程
startSystemServer(abiList, socketName);//3
}
Log.i(TAG, "Accepting command socket connections");
//等待客户端请求
runSelectLoop(abiList);//4
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}复制代码
这些内容在Android系统启动流程(二)解析Zygote进程启动过程讲过,但为了更好的理解我再讲一遍。注释1处经过registerZygoteSocket函数来建立一个Server端的Socket,这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来建立新的应用程序进程。注释2处用来预加载类和资源。注释3处用来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。注释4处调用runSelectLoop函数来等待ActivityManagerService的请求。咱们就来查看runSelectLoop函数:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();//2
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
...
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();//1
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}复制代码
当有ActivityManagerService的请求数据到来时会调用注释1处的代码,结合注释2处的代码,咱们得知注释1处的代码实际上是调用ZygoteConnection的runOnce函数来处理请求的数据:
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();//1
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
...
try {
parsedArgs = new Arguments(args);//2
...
/** * 3 */
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (ErrnoException ex) {
....
}
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}复制代码
在注释1处调用readArgumentList函数来获取应用程序进程的启动参数,并在注释2处将readArgumentList函数返回的字符串封装到Arguments对象parsedArgs中。注释3处调用Zygote的forkAndSpecialize函数来建立应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。forkAndSpecialize函数主要是经过fork当前进程来建立一个子进程的,若是pid等于0,则说明是在新建立的子进程中执行的,就会调用handleChildProc函数来启动这个子进程也就是应用程序进程,以下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
...
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}复制代码
handleChildProc函数中调用了RuntimeInit的zygoteInit函数,以下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();//1
applicationInit(targetSdkVersion, argv, classLoader);//2
}复制代码
注释1处会在新建立的应用程序进程中建立Binder线程池,这个在下一篇文章会详细介绍。在注释2处调用了applicationInit函数:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
return;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
invokeStaticMain(args.startClass, args.startArgs, classLoader);//1
}复制代码
在applicationInit中会在注释1处调用invokeStaticMain函数,须要注意的是第一个参数args.startClass,这里指的就是此篇文章开头提到的参数:android.app.ActivityThread。接下来咱们查看invokeStaticMain函数,以下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);//1
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });//2
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
}
...
throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
}复制代码
能够看到注释1处经过反射来得到android.app.ActivityThread类,接下来在注释2处来得到ActivityThread的main函数,并将main函数传入到注释3处的ZygoteInit中的MethodAndArgsCaller类的构造函数中,MethodAndArgsCaller类内部会经过反射调用ActivityThread的main函数,这样应用程序进程就建立完成了。
咱们首先来看RuntimeInit类的zygoteInit函数,以下所示
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();//1
applicationInit(targetSdkVersion, argv, classLoader);
}复制代码
注释1处会在新建立的应用程序进程中建立Binder线程池,来查看nativeZygoteInit函数:
private static final native void nativeZygoteInit();复制代码
很明显nativeZygoteInit是一个jni方法,它对应的函数是什么呢。在 AndroidRuntime.cpp的JNINativeMethod数组中咱们得知它对应的函数是com_android_internal_os_RuntimeInit_nativeZygoteInit,以下所示。
frameworks/base/core/jni/AndroidRuntime.cpp
static const JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
{ "nativeSetExitWithoutCleanup", "(Z)V",
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};复制代码
接着来查看 com_android_internal_os_RuntimeInit_nativeZygoteInit函数:
frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}复制代码
gCurRuntime是在AndroidRuntime初始化就建立的。以下所示。
frameworks/base/core/jni/AndroidRuntime.cpp
AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
mExitWithoutCleanup(false),
mArgBlockStart(argBlockStart),
mArgBlockLength(argBlockLength)
{
...
gCurRuntime = this;
}复制代码
在Android系统启动流程(二)解析Zygote进程启动过程这篇文章咱们得知AppRuntime继承AndroidRuntime,AppRuntime建立时就会调用AndroidRuntime的构造函数,gCurRuntime就会被初始化,它指向的是AppRuntime,所以咱们来查看AppRuntime的onZygoteInit函数,AppRuntime的实如今app_main.cpp中,以下所示。
frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}复制代码
最后一行会调用ProcessState的startThreadPool函数:
frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}复制代码
支持Binder通讯的进程中都有一个ProcessState类,它里面有一个mThreadPoolStarted 变量,来表示Binder线程池是否已经被启动过,默认值为false。在每次调用这个函数时都会先去检查这个标记,从而确保Binder线程池只会被启动一次。若是Binder线程池未被启动则设置mThreadPoolStarted为true,最后调用spawnPooledThread函数来建立线程池中的第一个线程,也就是线程池的main线程,以下所示。
frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());//1
}
}复制代码
能够看到Binder线程为一个PoolThread。注释1调用PoolThread的run函数来启动一个启动一个新的线程。来查看PoolThread类里作了什么:
frameworks/native/libs/binder/ProcessState.cpp
class PoolThread : public Thread
{
..
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);//1
return false;
}
const bool mIsMain;
};复制代码
PoolThread类继承了Thread类。注释1处会将调用IPCThreadState的joinThreadPool函数,将当前线程注册到Binder驱动程序中,这样咱们建立的线程就加入了Binder线程池中,这样新建立的应用程序进程就支持Binder进程间通讯了,Binder线程池启动过程就讲到这,接下来咱们来学习消息循环建立过程。
首先咱们回到上篇最后讲到的RuntimeInit的invokeStaticMain函数,代码以下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
...
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}复制代码
invokeStaticMain函数在上篇已经讲过,这里再也不赘述,主要是看最后一行,会抛出一个MethodAndArgsCaller异常,这个异常会被ZygoteInit的main函数捕获,以下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
try {
...
} catch (MethodAndArgsCaller caller) {
caller.run();//1
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}复制代码
注释1处捕获到MethodAndArgsCaller 时会执行caller的run函数,以下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static class MethodAndArgsCaller extends Exception implements Runnable {
private final Method mMethod;
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });//1
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
...
throw new RuntimeException(ex);
}
}
}复制代码
根据上一篇文章咱们得知,mMethod指的就是ActivityThread的main函数,mArgs 指的是应用程序进程的启动参数。在注释1处调用ActivityThread的main函数,代码以下所示。
frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
...
Looper.prepareMainLooper();//1
ActivityThread thread = new ActivityThread();//2
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();//3
throw new RuntimeException("Main thread loop unexpectedly exited");
}复制代码
注释1处在当前应用程序进程中建立消息循环,注释2处建立ActivityThread,注释3处调用Looper的loop,使得Looper开始工做,开始处理消息。能够看出,系统在应用程序进程启动完成后,就会建立一个消息循环,用来方便的使用Android的消息处理机制。
欢迎关注个人微信公众号,第一时间得到博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,便可关注。