1 进程启动过程
Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制;这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的。
Android应用程序框架层创建的应用程序进程的入口函数是ActivityThread.main比较好理解,即进程创建完成之后,Android应用程序框架层就会在这个进程中将ActivityThread类加载进来,然后执行它的main函数,这个main函数就是进程执行消息循环的地方了。Android应用程序框架层创建的应用程序进程天然支持Binder进程间通信机制这个特点应该怎么样理解呢?前面我们在学习Android系统的Binder进程间通信机制时说到,它具有四个组件,分别是驱动程序、守护进程、Client以及Server,其中Server组件在初始化时必须进入一个循环中不断地与Binder驱动程序进行到交互,以便获得Client组件发送的请求,具体可参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,但是,当我们在Android应用程序中实现Server组件的时候,我们并没有让进程进入一个循环中去等待Client组件的请求,然而,当Client组件得到这个Server组件的远程接口时,却可以顺利地和Server组件进行进程间通信,这就是因为Android应用程序进程在创建的时候就已经启动了一个线程池来支持Server组件和Binder驱动程序之间的交互了,这样,极大地方便了在Android应用程序中创建Server组件。
在Android应用程序框架层中,是由ActivityManagerService组件负责为Android应用程序创建新的进程的,它本来也是运行在一个独立的进程之中,不过这个进程是在系统启动的过程中创建的。ActivityManagerService组件一般会在什么情况下会为应用程序创建一个新的进程呢?当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程了,然后在这个新的进程中启动这个Activity或者Service,具体可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析、Android应用程序启动过程源代码分析和Android应用程序在新的进程中启动新的Activity的方法和过程分析这三篇文章。
ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的,在深入分析这个过程之前,我们先来看一下进程创建过程的序列图,然后再详细分析每一个步骤。
Step 1.ActivityManagerService.startProcessLocked
这个函数定义在frameworks/base/services/Java/com/android/server/am/ActivityManagerService.java文件中:
public final class ActivityManagerService extendsActivityManagerNative implementsWatchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final voidstartProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr){
......
try{
intuid = app.info.uid;
int[] gids = null;
try{
gids = mContext.getPackageManager().getPackageGids(app.info.packageName);
} catch(PackageManager.NameNotFoundException e) {
......
}
......
int debugFlags = 0;
......
int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null);
......
} catch(RuntimeException e) {
......
}
}
......
}
它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,后面我们会看到。
Step 2. Process.start
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
public classProcess {
......
public static final int start(finalString processClass, finalString niceName, int uid, int gid, int[] gids, intdebugFlags, String[] zygoteArgs)
{
if(supportsProcesses()) {
try{
returnstartViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs);
} catch(ZygoteStartFailedEx ex) {
......
}
} else{
......
return 0;
}
}
......
}
这里的supportsProcesses函数返回值为true,它是一个Native函数,实现在frameworks/base/core/jni/android_util_Process.cpp文件中:
jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
{
returnProcessState::self()->supportsProcesses();
}
ProcessState::supportsProcesses函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
bool ProcessState::supportsProcesses() const
{
returnmDriverFD >= 0;
}
这里的mDriverFD是设备文件/dev/binder的打开描述符,如果成功打开了这个设备文件,那么它的值就会大于等于0,因此,它的返回值为true。
回到Process.start函数中,它调用startViaZygote函数进一步操作。
Step3. Process.startViaZygote
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
public classProcess {
......
private static int startViaZygote(finalString processClass, finalString niceName, final int uid,
final intgid, final int[] gids, intdebugFlags, String[] extraArgs) throwsZygoteStartFailedEx
{
intpid;
synchronized(Process.class) {
ArrayList argsForZygote = newArrayList();
// --runtime-init, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-init");
argsForZygote.add("--setuid="+ uid);
argsForZygote.add("--setgid="+ gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");
// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = newStringBuilder();
sb.append("--setgroups=");
intsz = gids.length;
for (int i = 0; i
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name="+ niceName);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for(String arg : extraArgs) {
argsForZygote.add(arg);
}
}
pid = zygoteSendArgsAndGetPid(argsForZygote);
}
}
......
}
这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。
Step 4. Process.zygoteSendAndGetPid
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
public classProcess {
......
private static intzygoteSendArgsAndGetPid(ArrayList args) throwsZygoteStartFailedEx
{
intpid;
openZygoteSocketIfNeeded();
try{
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure.
*/
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
intsz = args.size();
for (int i = 0; i
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw newZygoteStartFailedEx("embedded newlines not allowed");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
// Should there be a timeout on this?
pid = sZygoteInputStream.readInt();
if (pid
throw new ZygoteStartFailedEx("fork() failed");
}
} catch(IOException ex) {
......
}
returnpid;
}
......
}
这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:
public classProcess {
......
/**
* Tries to open socket to Zygote process if not already open. If
* already open, does nothing. May block and retry.
*/
private static voidopenZygoteSocketIfNeeded() throwsZygoteStartFailedEx
{
intretryCount;
if(sPreviousZygoteOpenFailed) {
/*
* If we've failed before, expect that we'll fail again and
* don't pause for retries.
*/
retryCount = 0;
} else{
retryCount = 10;
}
/*
* See bug #811181: Sometimes runtime can make it up before zygote.
* Really, we'd like to do something better to avoid this condition,
* but for now just wait a bit...
*/
for (int retry = 0; (sZygoteSocket == null) && (retry
{
if (retry > 0) {
try{
Log.i("Zygote", "Zygote not up yet, sleeping...");
Thread.sleep(ZYGOTE_RETRY_MILLIS);
} catch(InterruptedException ex) {
// should never happen
}
}
try{
sZygoteSocket = newLocalSocket();
sZygoteSocket.connect(newLocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream = newDataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter = newBufferedWriter(newOutputStreamWriter(sZygoteSocket.getOutputStream()), 256);
Log.i("Zygote", "Process: zygote socket opened");
sPreviousZygoteOpenFailed = false;
break;
} catch(IOException ex) {
......
}
}
......
}
......
}
这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。
Step 5. ZygoteInit.runSelectLoopMode
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
public classZygoteInit {
......
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoopMode() throwsMethodAndArgsCaller {
ArrayList fds = newArrayList();
ArrayList peers = newArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
intloopCount = GC_LOOP_COUNT;
while (true) {
intindex;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <&#61; 0) {
gc();
loopCount &#61; GC_LOOP_COUNT;
} else{
loopCount--;
}
try{
fdArray &#61; fds.toArray(fdArray);
index &#61; selectReadable(fdArray);
} catch(IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index
throw new RuntimeException("Error in select()");
} else if (index &#61;&#61; 0) {
ZygoteConnection newPeer &#61; acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else{
booleandone;
done &#61; peers.get(index).runOnce();
if(done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
当Step 4将数据通过Socket接口发送出去后&#xff0c;就会下面这个语句&#xff1a;
done &#61; peers.get(index).runOnce();
这里从peers.get(index)得到的是一个ZygoteConnection对象&#xff0c;表示一个Socket连接&#xff0c;因此&#xff0c;接下来就是调用ZygoteConnection.runOnce函数进一步处理了。
Step 6. ZygoteConnection.runOnce
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中&#xff1a;
classZygoteConnection
{
......
boolean runOnce() throwsZygoteInit.MethodAndArgsCaller
{
String args[];
Arguments parsedArgs &#61; null;
FileDescriptor[] descriptors;
try{
args &#61; readArgumentList();
descriptors &#61; mSocket.getAncillaryFileDescriptors();
} catch(IOException ex) {
......
return true;
}
......
/** the stderr of the most recent request, if avail */
PrintStream newStderr &#61; null;
if (descriptors !&#61; null && descriptors.length >&#61; 3) {
newStderr &#61; newPrintStream(new FileOutputStream(descriptors[2]));
}
intpid;
try{
parsedArgs &#61; newArguments(args);
applyUidSecurityPolicy(parsedArgs, peer);
applyDebuggerSecurityPolicy(parsedArgs);
applyRlimitSecurityPolicy(parsedArgs, peer);
applyCapabilitiesSecurityPolicy(parsedArgs, peer);
int[][] rlimits &#61; null;
if (parsedArgs.rlimits !&#61; null) {
rlimits &#61; parsedArgs.rlimits.toArray(intArray2d);
}
pid &#61; Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);
} catch(IllegalArgumentException ex) {
......
} catch(ZygoteSecurityException ex) {
......
}
if (pid &#61;&#61; 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr);
// should never happen
return true;
} else { /* pid !&#61; 0 */
// in parent...pid of
returnhandleParentProc(pid, descriptors, parsedArgs);
}
}
......
}
真正创建进程的地方就是在这里了&#xff1a;
pid &#61; Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);
有Linux开发经验的读者很容易看懂这个函数调用&#xff0c;这个函数会创建一个进程&#xff0c;而且有两个返回值&#xff0c;一个是在当前进程中返回的&#xff0c;一个是在新创建的进程中返回&#xff0c;即在当前进程的子进程中返回&#xff0c;在当前进程中的返回值就是新创建的子进程的pid值&#xff0c;而在子进程中的返回值是0。因为我们只关心创建的新进程的情况&#xff0c;因此&#xff0c;我们沿着子进程的执行路径继续看下去&#xff1a;
if (pid &#61;&#61; 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr);
// should never happen
return true;
} else {
/* pid !&#61; 0 */
......
}
这里就是调用handleChildProc函数了。
Step7. ZygoteConnection.handleChildProc
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中&#xff1a;
classZygoteConnection {
......
private voidhandleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throwsZygoteInit.MethodAndArgsCaller
{
......
if(parsedArgs.runtimeInit) {
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
} else{
......
}
}
......
}
由于在前面的Step 3中&#xff0c;指定了"--runtime-init"参数&#xff0c;表示要为新创建的进程初始化运行时库&#xff0c;因此&#xff0c;这里的parseArgs.runtimeInit值为true&#xff0c;于是就继续执行RuntimeInit.zygoteInit进一步处理了。
Step 8. RuntimeInit.zygoteInit
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中&#xff1a;
public classRuntimeInit {
......
public static final voidzygoteInit(String[] argv) throwsZygoteInit.MethodAndArgsCaller
{
// TODO: Doing this here works, but it seems kind of arbitrary. Find
// a better place. The goal is to set it up for applications, but not
// tools like am.
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
commonInit();
zygoteInitNative();
int curArg &#61; 0;
for ( /* curArg */; curArg
String arg &#61; argv[curArg];
if (arg.equals("--")) {
curArg&#43;&#43;;
break;
} else if (!arg.startsWith("--")) {
break;
} else if (arg.startsWith("--nice-name&#61;")) {
String niceName &#61; arg.substring(arg.indexOf(&#39;&#61;&#39;) &#43; 1);
Process.setArgV0(niceName);
}
}
if(curArg &#61;&#61; argv.length) {
Slog.e(TAG, "Missing classname argument to RuntimeInit!");
// let the process exit
return;
}
// Remaining arguments are passed to the start class&#39;s static main
String startClass &#61; argv[curArg&#43;&#43;];
String[] startArgs &#61; newString[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
invokeStaticMain(startClass, startArgs);
}
......
}
这里有两个关键的函数调用&#xff0c;一个是zygoteInitNative函数调用&#xff0c;一个是invokeStaticMain函数调用&#xff0c;前者就是执行Binder驱动程序初始化的相关工作了&#xff0c;正是由于执行了这个工作&#xff0c;才使得进程中的Binder对象能够顺利地进行Binder进程间通信&#xff0c;而后一个函数调用&#xff0c;就是执行进程的入口函数&#xff0c;这里就是执行startClass类的main函数了&#xff0c;而这个startClass即是我们在Step 1中传进来的"android.app.ActivityThread"值&#xff0c;表示要执行android.app.ActivityThread类的main函数。
我们先来看一下zygoteInitNative函数的调用过程&#xff0c;然后再回到RuntimeInit.zygoteInit函数中来&#xff0c;看看它是如何调用android.app.ActivityThread类的main函数的。
step 9. RuntimeInit.zygoteInitNative
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中&#xff1a;
public classRuntimeInit {
......
public static final native voidzygoteInitNative();
......
}
这里可以看出&#xff0c;函数zygoteInitNative是一个Native函数&#xff0c;实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中&#xff1a;
static voidcom_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
这里它调用了全局变量gCurRuntime的onZygoteInit函数&#xff0c;这个全局变量的定义在frameworks/base/core/jni/AndroidRuntime.cpp文件开头的地方&#xff1a;
staticAndroidRuntime* gCurRuntime &#61; NULL;
这里可以看出&#xff0c;它的类型为AndroidRuntime&#xff0c;它是在AndroidRuntime类的构造函数中初始化的&#xff0c;AndroidRuntime类的构造函数也是定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中&#xff1a;
AndroidRuntime::AndroidRuntime()
{
......
assert(gCurRuntime &#61;&#61; NULL); // one per process
gCurRuntime &#61; this;
}
那么这个AndroidRuntime类的构造函数又是什么时候被调用的呢&#xff1f;AndroidRuntime类的声明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中&#xff0c;如果我们打开这个文件会看到&#xff0c;它是一个虚拟类&#xff0c;也就是我们不能直接创建一个AndroidRuntime对象&#xff0c;只能用一个AndroidRuntime类的指针来指向它的某一个子类&#xff0c;这个子类就是AppRuntime了&#xff0c;它定义在frameworks/base/cmds/app_process/app_main.cpp文件中&#xff1a;
int main(int argc, const char* constargv[])
{
......
AppRuntime runtime;
......
}
而AppRuntime类继续了AndroidRuntime类&#xff0c;它也是定义在frameworks/base/cmds/app_process/app_main.cpp文件中&#xff1a;
class AppRuntime : publicAndroidRuntime
{
......
};
因此&#xff0c;在前面的com_android_internal_os_RuntimeInit_zygoteInit函数&#xff0c;实际是执行了AppRuntime类的onZygoteInit函数。
Step 10. AppRuntime.onZygoteInit
这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中&#xff1a;
class AppRuntime : publicAndroidRuntime
{
......
virtual voidonZygoteInit()
{
sp proc &#61; ProcessState::self();
if(proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
}
......
};
这里它就是调用ProcessState::startThreadPool启动线程池了&#xff0c;这个线程池中的线程就是用来和Binder驱动程序进行交互的了。
Step 11. ProcessState.startThreadPool
这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中&#xff1a;
voidProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if(!mThreadPoolStarted) {
mThreadPoolStarted &#61; true;
spawnPooledThread(true);
}
}
Step 12. ProcessState.spawnPooledThread
这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中&#xff1a;
void ProcessState::spawnPooledThread(boolisMain)
{
if(mThreadPoolStarted) {
int32_t s &#61; android_atomic_add(1, &mThreadPoolSeq);
charbuf[32];
sprintf(buf, "Binder Thread #%d", s);
LOGV("Spawning new pooled thread, name&#61;%s\n", buf);
sp t &#61; newPoolThread(isMain);
t->run(buf);
}
}
这里它会创建一个PoolThread线程类&#xff0c;然后执行它的run函数&#xff0c;最终就会执行PoolThread类的threadLoop函数了。
Step 13. PoolThread.threadLoop
这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中&#xff1a;
class PoolThread : publicThread
{
public:
PoolThread(boolisMain) : mIsMain(isMain)
{
}
protected:
virtual boolthreadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const boolmIsMain;
};
Step14. IPCThreadState.joinThreadPool
这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中&#xff1a;
void IPCThreadState::joinThreadPool(boolisMain)
{
......
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
......
status_t result;
do{
int32_t cmd;
......
// now get the next command to be processed, waiting if necessary
result &#61; talkWithDriver();
if(result >&#61; NO_ERROR) {
size_tIN &#61; mIn.dataAvail();
if (IN
cmd &#61; mIn.readInt32();
......
result &#61; executeCommand(cmd);
}
......
} while(result !&#61; -ECONNREFUSED && result !&#61; -EBADF);
......
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
这个函数首先告诉Binder驱动程序&#xff0c;这条线程要进入循环了&#xff1a;
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
然后在中间的while循环中通过talkWithDriver不断与Binder驱动程序进行交互&#xff0c;以便获得Client端的进程间调用&#xff1a;
result &#61; talkWithDriver();
获得了Client端的进程间调用后&#xff0c;就调用excuteCommand函数来处理这个请求&#xff1a;
result &#61; executeCommand(cmd);
最后&#xff0c;线程退出时&#xff0c;也会告诉Binder驱动程序&#xff0c;它退出了&#xff0c;这样Binder驱动程序就不会再在Client端的进程间调用分发给它了&#xff1a;
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
我们再来看看talkWithDriver函数的实现。
Step 15. talkWithDriver
这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中&#xff1a;
status_t IPCThreadState::talkWithDriver(booldoReceive)
{
......
binder_write_read bwr;
// Is the read buffer empty?
const boolneedRead &#61; mIn.dataPosition() >&#61; mIn.dataSize();
// We don&#39;t want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_toutAvail &#61; (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size &#61; outAvail;
bwr.write_buffer &#61; (long unsigned int)mOut.data();
// This is what we&#39;ll read.
if(doReceive && needRead) {
bwr.read_size &#61; mIn.dataCapacity();
bwr.read_buffer &#61; (long unsigned int)mIn.data();
} else{
bwr.read_size &#61; 0;
}
......
// Return immediately if there is nothing to do.
if ((bwr.write_size &#61;&#61; 0) && (bwr.read_size &#61;&#61; 0))
returnNO_ERROR;
bwr.write_consumed &#61; 0;
bwr.read_consumed &#61; 0;
status_t err;
do{
......
#if defined(HAVE_ANDROID_OS)
if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >&#61; 0)
err &#61; NO_ERROR;
else
err &#61; -errno;
#else
err &#61; INVALID_OPERATION;
#endif
......
}
} while(err &#61;&#61; -EINTR);
....
if(err >&#61; NO_ERROR) {
if(bwr..write_consumed > 0) {
if(bwr.write_consumed
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if(bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
......
returnNO_ERROR;
}
returnerr;
}
这个函数的具体作用可以参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文&#xff0c;它只要就是通过ioctl文件操作函数来和Binder驱动程序交互的了&#xff1a;
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
有了这个线程池之后&#xff0c;我们在开发Android应用程序的时候&#xff0c;当我们要和其它进程中进行通信时&#xff0c;只要定义自己的Binder对象&#xff0c;然后把这个Binder对象的远程接口通过其它途径传给其它进程后&#xff0c;其它进程就可以通过这个Binder对象的远程接口来调用我们的应用程序进程的函数了&#xff0c;它不像我们在C&#43;&#43;层实现Binder进程间通信机制的Server时&#xff0c;必须要手动调用IPCThreadState.joinThreadPool函数来进入一个无限循环中与Binder驱动程序交互以便获得Client端的请求&#xff0c;这样就实现了我们在文章开头处说的Android应用程序进程天然地支持Binder进程间通信机制。
细心的读者可能会发现&#xff0c;从Step 1到Step 9&#xff0c;都是在Android应用程序框架层运行的&#xff0c;而从Step 10到Step 15&#xff0c;都是在Android系统运行时库层运行的&#xff0c;这两个层次中的Binder进程间通信机制的接口一个是用Java来实现的&#xff0c;而另一个是用C&#43;&#43;来实现的&#xff0c;这两者是如何协作的呢&#xff1f;这就是通过JNI层来实现的了&#xff0c;具体可以参考Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析一文。
回到Step 8中的RuntimeInit.zygoteInit函数中&#xff0c;在初始化完成Binder进程间通信机制的基础设施后&#xff0c;它接着就要进入进程的入口函数了。
Step 16. RuntimeInit.invokeStaticMain
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中&#xff1a;
public classZygoteInit {
......
static voidinvokeStaticMain(ClassLoader loader, String className, String[] argv) throwsZygoteInit.MethodAndArgsCaller
{
Class cl;
try{
cl &#61; loader.loadClass(className);
} catch(ClassNotFoundException ex) {
......
}
Method m;
try{
m &#61; cl.getMethod("main", new Class[] { String[].class});
} catch(NoSuchMethodException ex) {
......
} catch(SecurityException ex) {
......
}
intmodifiers &#61; m.getModifiers();
......
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception&#39;s run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw newZygoteInit.MethodAndArgsCaller(m, argv);
}
......
}
前面我们说过&#xff0c;这里传进来的参数className字符串值为"android.app.ActivityThread"&#xff0c;这里就通ClassLoader.loadClass函数将它加载到进程中&#xff1a;
cl &#61; loader.loadClass(className);
然后获得它的静态成员函数main&#xff1a;
m &#61; cl.getMethod("main", new Class[] { String[].class});
函数最后并没有直接调用这个静态成员函数main&#xff0c;而是通过抛出一个异常ZygoteInit.MethodAndArgsCaller&#xff0c;然后让ZygoteInit.main函数在捕获这个异常的时候再调用android.app.ActivityThread类的main函数。为什么要这样做呢&#xff1f;注释里面已经讲得很清楚了&#xff0c;它是为了清理堆栈的&#xff0c;这样就会让android.app.ActivityThread类的main函数觉得自己是进程的入口函数&#xff0c;而事实上&#xff0c;在执行android.app.ActivityThread类的main函数之前&#xff0c;已经做了大量的工作了。
我们看看ZygoteInit.main函数在捕获到这个异常的时候做了什么事&#xff1a;
public classZygoteInit {
......
public static voidmain(String argv[]) {
try{
......
} catch(MethodAndArgsCaller caller) {
caller.run();
} catch(RuntimeException ex) {
......
}
}
......
}
它执行MethodAndArgsCaller的run函数&#xff1a;
public classZygoteInit {
......
public static class MethodAndArgsCaller extendsException implementsRunnable
{
/** method to call */
private finalMethod mMethod;
/** argument array */
private finalString[] mArgs;
publicMethodAndArgsCaller(Method method, String[] args) {
mMethod &#61; method;
mArgs &#61; args;
}
public voidrun() {
try{
mMethod.invoke(null, newObject[] { mArgs });
} catch(IllegalAccessException ex) {
......
} catch(InvocationTargetException ex) {
......
}
}
}
......
}
这里的成员变量mMethod和mArgs都是在前面构造异常对象时传进来的&#xff0c;这里的mMethod就对应android.app.ActivityThread类的main函数了&#xff0c;于是最后就通过下面语句执行这个函数&#xff1a;
mMethod.invoke(null, newObject[] { mArgs });
这样&#xff0c;android.app.ActivityThread类的main函数就被执行了。
Step 17. ActivityThread.main
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中&#xff1a;
public final classActivityThread {
......
public static final voidmain(String[] args)
{
SamplingProfilerIntegration.start();
Process.setArgV0("");
Looper.prepareMainLooper();
if (sMainThreadHandler &#61;&#61; null) {
sMainThreadHandler &#61; newHandler();
}
ActivityThread thread &#61; newActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
if(Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name &#61; (thread.mInitialApplication !&#61; null) ? thread.mInitialApplication.getPackageName()
: "";
Slog.i(TAG, "Main thread of " &#43; name &#43; " is now exiting");
}
......
}
从这里我们可以看出&#xff0c;这个函数首先会在进程中创建一个ActivityThread对象&#xff1a;
ActivityThread thread &#61; newActivityThread();
然后进入消息循环中&#xff1a;
Looper.loop();
这样&#xff0c;我们以后就可以在这个进程中启动Activity或者Service了。
至此&#xff0c;Android应用程序进程启动过程的源代码就分析完成了&#xff0c;它除了指定新的进程的入口函数是ActivityThread的main函数之外&#xff0c;还为进程内的Binder对象提供了Binder进程间通信机制的基础设施&#xff0c;由此可见&#xff0c;Binder进程间通信机制在Android系统中是何等的重要&#xff0c;而且是无处不在&#xff0c;想进一步学习Android系统的Binder进程间通信机制&#xff0c;请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。
2 进程创建
Android系统中的进程管理&#xff1a;进程的创建
2.1 概述
Android系统以Linux内核为基础&#xff0c;所以对于进程的管理自然离不开Linux本身提供的机制。例如&#xff1a;
· 通过fork来创建进行
· 通过信号量来管理进程
· 通过proc文件系统来查询和调整进程状态等
对于Android来说&#xff0c;进程管理的主要内容包括以下几个部分内容&#xff1a;
· 进程的创建
· 进程的优先级管理
· 进程的内存管理
· 进程的回收和死亡处理
本文会专门讲解进程的创建&#xff0c;其余部分将在后面的文章中讲解。
2.2 主要模块
为了便于下文的讲解&#xff0c;这里先介绍一下Android系统中牵涉到进程创建的几个主要模块。同时为了便于读者更详细的了解这些模块&#xff0c;这里也同时提供了这些模块的代码路径。
这里提到的代码路径是指AOSP的源码数中的路径。
关于如何获取AOSP源码请参见这里&#xff1a;Downloading the Source。
本文以Android N版本的代码为示例&#xff0c;所用到的Source Code Tags是&#xff1a;android-7.0.0_r1。
相关模块&#xff1a;
· app_process
代码路径&#xff1a;frameworks/base/cmds/app_process
说明&#xff1a;app_process是一个可执行程序&#xff0c;该程序的主要作用是启动zygote和system_server进程。
· Zygote
代码路径&#xff1a;frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
说明&#xff1a;zygote进程是所有应用进程的父进程&#xff0c;这是系统中一个非常重要的进程&#xff0c;下文我们会详细讲解。
[if !supportLists]· [endif]ActivityManager
代码路径&#xff1a;frameworks/base/services/core/java/com/android/server/am/
说明&#xff1a;am是ActivityManager的缩写。
这个目录下的代码负责了Android全部四大组件(Activity&#xff0c;Service&#xff0c;ContentProvider&#xff0c;BroadcastReceiver)的管理&#xff0c;并且还掌控了所有应用程序进程的创建和进程的优先级管理。
因此&#xff0c;这个部分的内容将是本系列文章讲解的重点。
2.3 关于进程
在Android系统中&#xff0c;进程可以大致分为系统进程和应用进程两大类。
系统进程是系统内置的(例如&#xff1a;init&#xff0c;zygote&#xff0c;system_server进程)&#xff0c;属于操作系统必不可少的一部分。系统进程的作用在于&#xff1a;
· 管理硬件设备
· 提供访问设备的基本能力
· 管理应用进程
应用进程是指应用程序运行的进程。这些应用程序可能是系统出厂自带的(例如Launcher&#xff0c;电话&#xff0c;短信等应用)&#xff0c;也可能是用户自己安装的(例如&#xff1a;微信&#xff0c;支付宝等)。
系统进程的数量通常是固定的(出厂或者系统升级之后就确定了)&#xff0c;并且系统进程通常是一直存活&#xff0c;常驻内存的。系统进程的异常退出将可能导致设备无法正常使用。
而应用程序和应用进程在每个人使用的设备上通常是各不一样的。如何管理好这些不确定的应用进程&#xff0c;就是操作系统本身要仔细考虑的内容。也是衡量一个操作系统好坏的标准之一。
在本文中&#xff0c;我们会介绍init&#xff0c;zygote和system_server三个系统进程。
除此之外&#xff0c;本系列文章将会把主要精力集中在讲解Android系统如何管理应用进程上。
2.4 init进程(核心)
init进程是一切的开始&#xff0c;在Android系统中&#xff0c;所有进程的进程号都是不确定的&#xff0c;唯独init进程的进程号一定是1。因为这个进程一定是系统起来的第一个进程。并且&#xff0c;init进程掌控了整个系统的启动逻辑。
我们知道&#xff0c;Android可能运行在各种不同的平台&#xff0c;不同的设备上。因此&#xff0c;启动的逻辑是不尽相同的。为了适应各种平台和设备的需求&#xff0c;init进程的初始化工作通过init.rc配置文件来管理。你可以在AOSP源码的system/core/rootdir/路径找到这些配置文件。配置文件的主入口文件是init.rc&#xff0c;这个文件会通过import引入其他几个文件。
在本文中&#xff0c;我们统称这些文件为init.rc。init.rc通过Android Init Language来进行配置。
建议读者大致阅读一下其语法说明 。
init.rc中配置了系统启动的时候该做哪些事情&#xff0c;以及启动哪些系统进程。
这其中有两个特别重要的进程就是&#xff1a;zygote和system_server进程。
· zygote的中文意思是“受精卵“。这是一个很有寓意的名称&#xff1a;所有的应用进程都是由zygote fork出来的子进程&#xff0c;因此zygote进程是所有应用进程的父进程。
· system_server 这个进程正如其名称一样&#xff0c;这是一个系统服务器。Framework层的几乎所有服务都位于这个进程中。这其中就包括管理四大组件的ActivityManagerService。
2.5 Zygote进程
init.rc文件会根据平台不一样&#xff0c;选择下面几个文件中的一个来启动zygote进程&#xff1a;
· init.zygote32.rc
· init.zygote32_64.rc
· init.zygote64.rc
· init.zygote64_32.rc
这几个文件的内容是大致一致的&#xff0c;仅仅是为了不同平台服务的。这里我们以init.zygote32.rc的文件为例&#xff0c;来看看其中的内容&#xff1a;
service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660root system
onrestart write/sys/android_power/request_state wake
onrestart write/sys/power/state on
onrestart restartaudioserver
onrestart restartcameraserver
onrestart restart media
onrestart restart netd
writepid/dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
在这段配置文件中(如果你不明白这段配置的含义&#xff0c;请阅读一下文档&#xff1a;Android Init Language)&#xff0c;启动了一个名称叫做zygote的服务进程。这个进程是通过/system/bin/app_process这个可执行程序创建的。
并且在启动这个可执行程序的时候&#xff0c;传递了&#96;-Xzygote/system/bin --zygote --start-system-server
class main&#96;这些参数。
要知道这里到底做了什么&#xff0c;我们需要看一下app_process的源码。app_process的源码在这个路径&#xff1a;frameworks/base/cmds/app_process/app_main.cpp。
这个文件的main函数的有如下代码&#xff1a;
int main(int argc, char*const argv[])
{
...
while (i const char* arg &#61; argv[i&#43;&#43;]; if (strcmp(arg, "--zygote")&#61;&#61; 0) { zygote &#61; true; niceName &#61; ZYGOTE_NICE_NAME; } else if (strcmp(arg,"--start-system-server") &#61;&#61; 0) { startSystemServer &#61; true; ... } ... if (!className.isEmpty()) { ... } else { ... if (startSystemServer) { args.add(String8("start-system-server")); } } ... if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args,zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit",args, zygote); } else { fprintf(stderr, "Error: no classname or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: noclass name or --zygote supplied."); return 10; } } 这里会判断&#xff0c; · 如果执行这个命令时带了--zygote参数&#xff0c;就会通过runtime.start启动com.android.internal.os.ZygoteInit。 · 如果参数中带有--start-system-server参数&#xff0c;就会将start-system-server添加到args中。 这段代码是C&#43;&#43;实现的。在执行这段代码的时候还没有任何Java的环境。而runtime.start就是启动Java虚拟机&#xff0c;并在虚拟机中启动指定的类。于是接下来的逻辑就在ZygoteInit.java中了。 这个文件的main函数主要代码如下&#xff1a; public static voidmain(String argv[]) { ... try { ... boolean startSystemServer &#61; false; String socketName &#61; "zygote"; String abiList &#61; null; for (int i &#61; 1; i if("start-system-server".equals(argv[i])) { startSystemServer &#61; true; } else if(argv[i].startsWith(ABI_LIST_ARG)) { ... } } ... registerZygoteSocket(socketName); ... preload(); ... Zygote.nativeUnmountStorageOnInit(); ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { startSystemServer(abiList,socketName); } Log.i(TAG, "Accepting commandsocket connections"); runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died withexception", ex); closeServerSocket(); throw ex; } } 在这段代码中&#xff0c;我们主要关注如下几行&#xff1a; 1. 通过 registerZygoteSocket(socketName); 注册Zygote Socket 2. 通过 preload(); 预先加载所有应用都需要的公共资源 3. 通过 startSystemServer(abiList, socketName); 启动system_server 4. 通过 runSelectLoop(abiList); 在Looper上等待连接 这里需要说明的是&#xff1a;zygote进程启动之后&#xff0c;会启动一个socket套接字&#xff0c;并通过Looper一直在这个套接字上等待连接。 所有应用进程都是通过发送数据到这个套接字上&#xff0c;然后由zygote进程创建的。 这里还有一点说明的是&#xff1a; 在Zygote进程中&#xff0c;会通过preload函数加载需要应用程序都需要的公共资源。 预先加载这些公共资源有如下两个好处&#xff1a; · 加快应用的启动速度 因为这些资源已经在zygote进程启动的时候加载好了 · 通过共享的方式节省内存 这是Linux本身提供的机制&#xff1a;父进程已经加载的内容可以在子进程中进行共享&#xff0c;而不用多份数据拷贝(除非子进程对这些数据进行了修改。) preload的资源主要是Framework相关的一些基础类和Resource资源&#xff0c;而这些资源正是所有应用都需要的&#xff1a; 开发者通过Android SDK开发应用所调用的API实现都在Framework中。 static void preload() { Log.d(TAG,"begin preload"); Trace.traceBegin(Trace.TRACE_TAG_DALVIK,"BeginIcuCachePinning"); beginIcuCachePinning(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); Trace.traceBegin(Trace.TRACE_TAG_DALVIK,"PreloadClasses"); preloadClasses(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources"); preloadResources(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL"); preloadOpenGL(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); preloadSharedLibraries(); preloadTextResources(); WebViewFactory.prepareWebViewInZygote(); endIcuCachePinning(); warmUpJcaProviders(); Log.d(TAG,"end preload"); } 2.6 system_server进程 上文已经提到&#xff0c;zygote进程起来之后会根据需要启动system_server进程。system_server进程中包含了大量的系统服务。例如&#xff1a; · 负责网络管理的NetworkManagementService&#xff1b; · 负责窗口管理的WindowManagerService&#xff1b; · 负责震动管理的VibratorService&#xff1b; · 负责输入管理的InputManagerService&#xff1b; 等等。关于system_server&#xff0c;我们今后会其他的文章中专门讲解&#xff0c;这里不做过多说明。 在本文中&#xff0c;我们只关注system_server中的ActivityManagerService这个系统服务。 2.7 ActivityManagerService 上文中提到&#xff1a;zygote进程在启动之后会启动一个socket&#xff0c;然后一直在这个socket等待连接。而会连接它的就是ActivityManagerService。因为ActivityManagerService掌控了所有应用进程的创建。所有应用程序的进程都是由ActivityManagerService通过socket发送请求给Zygote进程&#xff0c;然后由zygote fork创建的。 ActivityManagerService通过Process.start方法来请求zygote创建进程&#xff1a; public static finalProcessStartResult 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) { Log.e(LOG_TAG, "Starting VM processthrough Zygote failed"); throw newRuntimeException("Starting VM process through Zygote failed", ex); } } 这个函数会将启动进程所需要的参数组装好&#xff0c;并通过socket发送给zygote进程。然后zygote进程根据发送过来的参数将进程fork出来。 在ActivityManagerService中&#xff0c;调用Process.start的地方是下面这个方法&#xff1a; private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... Process.ProcessStartResult startResult &#61; Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); ... } 下文中我们会看到&#xff0c;所有四大组件进程的创建&#xff0c;都是调用这里的startProcessLocked这个方法而创建的。 对于每一个应用进程&#xff0c;在ActivityManagerService中&#xff0c;都有一个ProcessRecord与之对应。这个对象记录了应用进程的所有详细状态。 PS&#xff1a;对于ProcessRecord的内部结构&#xff0c;在下一篇文章中&#xff0c;我们会讲解。 为了查找方便&#xff0c;对于每个ProcessRecord会存在下面两个集合中。 · 按名称和uid组织的集合&#xff1a; /** * All of the applications we currently have running organized by name. * The keys are strings of the application package name (as * returned by the package manager), and the keys are ApplicationRecord * objects. */ final ProcessMap mProcessNames &#61; new ProcessMap(); · 按pid组织的集合&#xff1a; /** * All of the processes we currently have running organized by pid. * The keys are the pid running the application. * NOTE: This object is protected by its own lock, NOT the global * activity manager lock! */ final SparseArray mPidsSelfLocked &#61; new SparseArray(); 下面这幅图小节了上文的这些内容&#xff1a; 2.8 关于应用组件 Processes and Threads 提到&#xff1a; “当某个应用组件启动且该应用没有运行其他任何组件时&#xff0c;Android 系统会使用单个执行线程为应用启动新的 Linux 进程。” 因此&#xff0c;四大组件中的任何一个先起来都会导致应用进程的创建。下文我们就详细看一下&#xff0c;它们启动时&#xff0c;各自是如何导致应用进程的创建的。 PS&#xff1a;四大组件的管理本身又是一个比较大的话题&#xff0c;限于篇幅关系&#xff0c;这里不会非常深入的讲解&#xff0c;这里主要是讲解四大组件与进程创建的关系。 在应用程序中&#xff0c;开发者通过&#xff1a; · startActivity(Intent intent) 来启动Activity · startService(Intent service) 来启动Service · sendBroadcast(Intent intent) 来发送广播 · ContentResolver 中的接口来使用ContentProvider 这其中&#xff0c;startActivity&#xff0c;startService和sendBroadcast还有一些重载方法。 其实这里提到的所有这些方法&#xff0c;最终都是通过Binder调用到ActivityManagerService中&#xff0c;由其进行处理的。 这里特别说明一下&#xff1a;应用进程和ActivityManagerService所在进程(即system_server进程)是相互独立的&#xff0c;两个进程之间的方法通常是不能直接互相调用的。 而Android系统中&#xff0c;专门提供了Binder框架来提供进程间通讯和方法调用的能力。 调用关系如下图所示&#xff1a; 2.9 Activity与进程创建 在ActivityManagerService中&#xff0c;对每一个运行中的Activity都有一个ActivityRecord对象与之对应&#xff0c;这个对象记录Activity的详细状态。 ActivityManagerService中的startActivity方法接受Context.startActivity的请求&#xff0c;该方法代码如下&#xff1a; &#64;Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); } Activity的启动是一个非常复杂的过程。这里我们简单介绍一下背景知识&#xff1a; • ActivityManagerService中通过Stack和Task来管理Activity • 每一个Activity都属于一个Task&#xff0c;一个Task可能包含多个Activity。一个Stack包含多个Task • ActivityStackSupervisor类负责管理所有的Stack • Activity的启动过程会牵涉到&#xff1a; o Intent的解析 o Stack&#xff0c;Task的查询或创建 o Activity进程的创建 o Activity窗口的创建 o Activity的生命周期调度 Activity的管理结构如下图所示&#xff1a; 在Activity启动的最后&#xff0c;会将前一个Activity pause&#xff0c;将新启动的Activity resume以便被用户看到。 在这个时候&#xff0c;如果发现新启动的Activity进程还没有启动&#xff0c;则会通过startSpecificActivityLocked将其启动。整个调用流程如下&#xff1a; · ActivityManagerService.activityPaused &#61;> · ActivityStack.activityPausedLocked &#61;> · ActivityStack.completePauseLocked &#61;> · ActivityStackSupervisor.ensureActivitiesVisibleLocked&#61;> · ActivityStack.makeVisibleAndRestartIfNeeded &#61;> · ActivityStackSupervisor.startSpecificActivityLocked &#61;> · ActivityManagerService.startProcessLocked · ActivityStackSupervisor.startSpecificActivityLocked 关键代码如下&#xff1a; void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity&#39;s application already running? ProcessRecordapp &#61; mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); if (app !&#61; null&& app.thread !&#61; null) { ... } mService.startProcessLocked(r.processName, r.info.applicationInfo, true,0, "activity", r.intent.getComponent(), false, false, true); } 这里的ProcessRecord app 描述了Activity所在进程。 2.10 Service与进程创建 Service的启动相对于Activity来说要简单一些。在ActivityManagerService中&#xff0c;对每一个运行中的Service都有一个ServiceRecord对象与之对应&#xff0c;这个对象记录Service的详细状态。 ActivityManagerService中的startService方法处理Context.startServiceAPI的请求&#xff0c;相关代码&#xff1a; &#64;Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throwsTransactionTooLargeException { ... synchronized(this) { final intcallingPid &#61; Binder.getCallingPid(); final intcallingUid &#61; Binder.getCallingUid(); final longorigId &#61; Binder.clearCallingIdentity(); ComponentNameres &#61; mServices.startServiceLocked(caller, service, resolvedType, callingPid,callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } } 这段代码中的mServices对象是ActiveServices类型的&#xff0c;这个类专门负责管理活动的Service。 启动Service的调用流程如下&#xff1a; · ActivityManagerService.startService &#61;> · ActiveServices.startServiceLocked &#61;> · ActiveServices.startServiceInnerLocked &#61;> · ActiveServices.bringUpServiceLocked &#61;> · ActivityManagerService.startProcessLocked ActiveServices.bringUpServiceLocked会判断如果Service所在进程还没有启动&#xff0c;则通过ActivityManagerService.startProcessLocked将其启动。相关代码如下&#xff1a; // Not running -- get it started, and enqueue this servicerecord // to be executed when the app comes up. if (app &#61;&#61; null && !permissionsReviewRequired) { if((app&#61;mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", r.name, false, isolated, false)) &#61;&#61; null) { String msg &#61;"Unable to launch app " &#43; r.appInfo.packageName &#43; "/" &#43; r.appInfo.uid &#43; " for service" &#43; r.intent.getIntent() &#43; ": process is bad"; Slog.w(TAG,msg); bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc&#61; app; } } 这里的mAm 就是ActivityManagerService。 2.11 Provider与进程创建 在ActivityManagerService中&#xff0c;对每一个运行中的ContentProvider都有一个ContentProviderRecord对象与之对应&#xff0c;这个对象记录ContentProvider的详细状态。 开发者通过ContentResolver中的insert, delete, update, query这些API来使用ContentProvider。在ContentResolver的实现中&#xff0c;无论使用这里的哪个接口&#xff0c;ContentResolver都会先通过acquireProvider 这个方法来获取到一个类型为IContentProvider的远程接口。这个远程接口对接了ContentProvider的实现提供方。 同一个ContentProvider可能同时被多个模块使用&#xff0c;而调用ContentResolver接口的进程只是ContentProvider的一个客户端而已&#xff0c;真正的ContentProvider提供方是运行自身的进程中的&#xff0c;两个进程的通讯需要通过Binder的远程接口形式来调用。如下图所示&#xff1a; ContentResolver.acquireProvider最终会调用到ActivityManagerService.getContentProvider中&#xff0c;该方法代码如下&#xff1a; &#64;Override public final ContentProviderHolder getContentProvider(IApplicationThread caller, String name, int userId, boolean stable) { enforceNotIsolatedCaller("getContentProvider"); if (caller &#61;&#61; null) { String msg &#61;"null IApplicationThread when getting content provider " &#43; name; Slog.w(TAG, msg); throw new SecurityException(msg); } // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal with cross-user grant. return getContentProviderImpl(caller, name, null, stable, userId); } 而在getContentProviderImpl这个方法中&#xff0c;会判断对应的ContentProvider进程有没有启动&#xff0c;如果没有&#xff0c;则通过startProcessLocked方法将其启动。 2.12 Receiver与进程创建 开发者通过Context.sendBroadcast接口来发送广播。ActivityManagerService.broadcastIntent方法了对应广播发送的处理。 广播是一种一对多的消息形式&#xff0c;广播接受者的数量是不确定的。因此发送广播本身可能是一个很耗时的过程(因为要逐个通知)。 在ActivityManagerService内部&#xff0c;是通过队列的形式来管理广播的&#xff1a; · BroadcastQueue 描述了一个广播队列 · BroadcastRecord 描述了一个广播事件 在ActivityManagerService中&#xff0c;如果收到了一个发送广播的请求&#xff0c;会先创建一个BroadcastRecord接着将其放入BroadcastQueue中。 然后通知队列自己去处理这个广播。然后ActivityManagerService自己就可以继续处理其他请求了。 广播队列本身是在另外一个线程处理广播的发送的&#xff0c;这样保证的ActivityManagerService主线程的负载不会太重。 在BroadcastQueue.processNextBroadcast(boolean fromMsg) 方法中真正实现了通知广播事件到接受者的逻辑。在这个方法&#xff0c;如果发现接受者(即BrodcastReceiver)还没有启动&#xff0c;便会通过ActivityManagerService.startProcessLocked方法将其启动。相关如下所示&#xff1a; final void processNextBroadcast(boolean fromMsg) { ... // Hard case: need to instantiate the receiver, possibly starting its application process to host it. ResolveInfo info &#61; (ResolveInfo)nextReceiver; ComponentName component &#61; new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name); ... // Not running -- get it started, to be executed when the app comes up. if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,"Need to start app [" &#43; mQueueName &#43; "] " &#43; targetProcess &#43; " for broadcast " &#43; r); if ((r.curApp&#61;mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast", r.curComponent, (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) !&#61; 0, false, false)) &#61;&#61; null) { // Ah, this recipient is unavailable. Finish it if necessary, //and mark the broadcast record as ready for the next. Slog.w(TAG,"Unable to launch app " &#43; info.activityInfo.applicationInfo.packageName &#43; "/" &#43; info.activityInfo.applicationInfo.uid &#43; " for broadcast " &#43; r.intent &#43; ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); r.state &#61; BroadcastRecord.IDLE; return; } mPendingBroadcast &#61; r; mPendingBroadcastRecvIndex &#61; recIdx; } } 至此&#xff0c;四大组件的启动就已经分析完了。 3 参考链接 Android开发之多进程详解 Android 应用内多进程实现 单APK应用多进程 ANDROID多进程需要注意的一个地方 Android 开发中踩过的坑之八:多进程问题 Android中应用多进程的整理总结 Android 后台任务型App多进程架构演化 Android应用内多进程分析和研究 Android开启多进程 Android中单APK应用多进程 Android单应用开多进程与单进程跑多应用 Android应用程序进程启动过程的源代码分析 Android应用程序在新的进程中启动新的Activity的方法和过程分析 (Good)深入理解Dalvik虚拟机- Android应用进程启动过程分析 Android基础 Android应用内多进程分析和研究 Android后台保活实践总结&#xff1a;即时通讯应用无法根治的“顽疾” Android系统中的进程管理&#xff1a;进程的创建 理解Android进程创建流程 android应用创建子进程的方法探究