原文出處——>[Android應用程序進程啟動過程的源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6747696)
Android應用程序框架層創建的應用程序進程具有兩個特點
* 一、進程的入口函數是ActivityThread.main
* 二、進程天然支持Binder進程間通信機制;
這兩個特點都是在進程的初始化過程中實現的,本文將詳細分析Android應用程序進程創建過程中是如何實現這兩個特點的。
Android應用程序框架層創建的應用程序進程的入口函數是ActivityThread.main比較好理解,即進程創建完成之后,Android應用程序框架層就會在這個進程中將ActivityThread類加載進來,然后執行它的main函數,這個main函數就是進程執行消息循環的地方了。
Android應用程序框架層創建的應用程序進程天然支持Binder進程間通信機制這個特點應該怎么樣理解呢?
前面我們在學習[Android系統的Binder進程間通信機制](http://blog.csdn.net/luoshengyang/article/details/6618363)時說到,它具有四個組件,分別是**驅動程序、守護進程、Client以及Server**,其中Server組件在初始化時必須進入一個循環中不斷地與Binder驅動程序進行到交互,以便獲得Client組件發送的請求,具體可參考[Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6629298)一文,但是,當我們在Android應用程序中實現Server組件的時候,我們并沒有讓進程進入一個循環中去等待Client組件的請求,然而,當Client組件得到這個Server組件的遠程接口時,卻可以順利地和Server組件進行進程間通信,這就是因為Android應用程序進程在創建的時候就已經啟動了一個線程池來支持Server組件和Binder驅動程序之間的交互了,這樣,極大地方便了在Android應用程序中創建Server組件。
在Android應用程序框架層中,是**由ActivityManagerService組件負責為Android應用程序創建新的進程的,它本來也是運行在一個獨立的進程之中,不過這個進程是在系統啟動的過程中創建的**。
ActivityManagerService組件一般會在什么情況下會為應用程序創建一個新的進程呢?
當系統決定要在一個新的進程中啟動一個Activity或者Service時,它就會創建一個新的進程了,然后在這個新的進程中啟動這個Activity或者Service,具體可以參考[Android系統在新進程中啟動自定義服務過程(startService)的原理分析](http://blog.csdn.net/luoshengyang/article/details/6677029)、[Android應用程序啟動過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6689748)和[Android應用程序在新的進程中啟動新的Activity的方法和過程分析](http://blog.csdn.net/luoshengyang/article/details/6720261)這三篇文章。
ActivityManagerService啟動新的進程是從其成員函數startProcessLocked開始的,在深入分析這個過程之前,我們先來看一下進程創建過程的序列圖,然后再詳細分析每一個步驟。大圖請[點擊這里](http://img.my.csdn.net/uploads/201109/5/0_1315236533f7n7.gif)

**Step 1. [ActivityManagerService](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java).startProcessLocked**
這個函數定義在**frameworks/base/services/java/com/android/server/am/ActivityManagerService.java**文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
......
try {
int uid = 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](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/core/java/android/os/Process.java).start**
這個函數定義在**frameworks/base/core/java/android/os/Process.java**文件中:
~~~
public class Process {
......
public static final int start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags,
String[] zygoteArgs)
{
if (supportsProcesses()) {
try {
return startViaZygote(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)
{
return ProcessState::self()->supportsProcesses();
}
~~~
**ProcessState::supportsProcesses**函數定義在**frameworks/base/libs/binder/ProcessState.cpp**文件中:
~~~
bool ProcessState::supportsProcesses() const
{
return mDriverFD >= 0;
}
~~~
這里的mDriverFD是設備文件/dev/binder的打開描述符,如果成功打開了這個設備文件,那么它的值就會大于等于0,因此,它的返回值為true。
回到Process.start函數中,它調用startViaZygote函數進一步操作。
**Step 3. Process.startViaZygote**
這個函數定義在**frameworks/base/core/java/android/os/Process.java**文件中:
~~~
public class Process {
......
private static int startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags,
String[] extraArgs)
throws ZygoteStartFailedEx {
int pid;
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --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 = 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());
}
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 class Process {
......
private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
throws ZygoteStartFailedEx {
int pid;
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();
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");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
// Should there be a timeout on this?
pid = sZygoteInputStream.readInt();
if (pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
} catch (IOException ex) {
......
}
return pid;
}
......
}
~~~
這里的sZygoteWriter是一個Socket寫入流,是由openZygoteSocketIfNeeded函數打開的:
~~~
public class Process {
......
/**
* Tries to open socket to Zygote process if not already open. If
* already open, does nothing. May block and retry.
*/
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
int retryCount;
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 < (retryCount + 1))
; 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 = new LocalSocket();
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
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](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java).runSelectLoopMode**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/ZygoteInit.java**文件中:
~~~
public class ZygoteInit {
......
/**
* 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() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* 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 <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
~~~
當Step 4將數據通過Socket接口發送出去后,就會下面這個語句:
~~~
done = peers.get(index).runOnce();
~~~
這里從peers.get(index)得到的是一個ZygoteConnection對象,表示一個Socket連接,因此,接下來就是調用ZygoteConnection.runOnce函數進一步處理了。
**Step 6. [ZygoteConnection](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java).runOnce**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java**文件中:
~~~
class ZygoteConnection {
......
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
......
return true;
}
......
/** the stderr of the most recent request, if avail */
PrintStream newStderr = null;
if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(
new FileOutputStream(descriptors[2]));
}
int pid;
try {
parsedArgs = new Arguments(args);
applyUidSecurityPolicy(parsedArgs, peer);
applyDebuggerSecurityPolicy(parsedArgs);
applyRlimitSecurityPolicy(parsedArgs, peer);
applyCapabilitiesSecurityPolicy(parsedArgs, peer);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
} catch (IllegalArgumentException ex) {
......
} catch (ZygoteSecurityException ex) {
......
}
if (pid == 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr);
// should never happen
return true;
} else { /* pid != 0 */
// in parent...pid of < 0 means failure
return handleParentProc(pid, descriptors, parsedArgs);
}
}
......
}
~~~
真正創建進程的地方就是在這里了:
~~~
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
~~~
有Linux開發經驗的讀者很容易看懂這個函數調用,這個函數會創建一個進程,而且有兩個返回值,一個是在當前進程中返回的,一個是在新創建的進程中返回,即在當前進程的子進程中返回,在當前進程中的返回值就是新創建的子進程的pid值,而在子進程中的返回值是0。因為我們只關心創建的新進程的情況,因此,我們沿著子進程的執行路徑繼續看下去:
~~~
if (pid == 0) {
// in child
handleChildProc(parsedArgs, descriptors, newStderr);
// should never happen
return true;
} else { /* pid != 0 */
......
}
~~~
這里就是調用handleChildProc函數了。
**Step 7. ZygoteConnection.handleChildProc**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java**文件中:
~~~
class ZygoteConnection {
......
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
......
if (parsedArgs.runtimeInit) {
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
} else {
......
}
}
......
}
~~~
由于在前面的Step 3中,指定了"--runtime-init"參數,表示要為新創建的進程初始化運行時庫,因此,這里的parseArgs.runtimeInit值為true,于是就繼續執行RuntimeInit.zygoteInit進一步處理了。
**Step 8. [RuntimeInit](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java).zygoteInit**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/RuntimeInit.java**文件中:
~~~
public class RuntimeInit {
......
public static final void zygoteInit(String[] argv)
throws ZygoteInit.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 = 0;
for ( /* curArg */ ; curArg < argv.length; curArg++) {
String arg = argv[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
} else if (arg.startsWith("--nice-name=")) {
String niceName = arg.substring(arg.indexOf('=') + 1);
Process.setArgV0(niceName);
}
}
if (curArg == argv.length) {
Slog.e(TAG, "Missing classname argument to RuntimeInit!");
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
invokeStaticMain(startClass, startArgs);
}
......
}
~~~
這里有兩個關鍵的函數調用,一個是zygoteInitNative函數調用,一個是invokeStaticMain函數調用,前者就是執行Binder驅動程序初始化的相關工作了,正是由于執行了這個工作,才使得進程中的Binder對象能夠順利地進行Binder進程間通信,而后一個函數調用,就是執行進程的入口函數,這里就是執行startClass類的main函數了,而這個startClass即是我們在Step 1中傳進來的`"android.app.ActivityThread"`值,表示要執行android.app.ActivityThread類的main函數。
我們先來看一下zygoteInitNative函數的調用過程,然后再回到RuntimeInit.zygoteInit函數中來,看看它是如何調用android.app.ActivityThread類的main函數的。
**step 9. RuntimeInit.zygoteInitNative**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/RuntimeInit.java**文件中:
~~~
public class RuntimeInit {
......
public static final native void zygoteInitNative();
......
}
~~~
這里可以看出,函數zygoteInitNative是一個Native函數,實現在**frameworks/base/core/jni/AndroidRuntime.cpp**文件中:
~~~
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
~~~
這里它調用了全局變量gCurRuntime的onZygoteInit函數,這個全局變量的定義在**frameworks/base/core/jni/AndroidRuntime.cpp**文件開頭的地方:
~~~
done = peers.get(index).runOnce();
~~~
這里可以看出,它的類型為AndroidRuntime,它是在AndroidRuntime類的構造函數中初始化的,AndroidRuntime類的構造函數也是定義在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
~~~
AndroidRuntime::AndroidRuntime()
{
......
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
~~~
那么這個AndroidRuntime類的構造函數又是什么時候被調用的呢?AndroidRuntime類的聲明在**frameworks/base/include/android_runtime/AndroidRuntime.h**文件中,如果我們打開這個文件會看到,它是一個虛擬類,也就是我們不能直接創建一個AndroidRuntime對象,只能用一個AndroidRuntime類的指針來指向它的某一個子類,這個子類就是AppRuntime了,它定義在frameworks/base/cmds/app_process/app_main.cpp文件中:
~~~
int main(int argc, const char* const argv[])
{
......
AppRuntime runtime;
......
}
~~~
而AppRuntime類繼續了AndroidRuntime類,它也是定義在**frameworks/base/cmds/app_process/app_main.cpp**文件中:
~~~
class AppRuntime : public AndroidRuntime
{
......
};
~~~
因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函數,實際是執行了AppRuntime類的onZygoteInit函數。
**Step 10. AppRuntime.onZygoteInit**
這個函數定義在**frameworks/base/cmds/app_process/app_main.cpp**文件中:
~~~
class AppRuntime : public AndroidRuntime
{
......
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
}
......
};
~~~
這里它就是調用ProcessState::startThreadPool啟動線程池了,這個線程池中的線程就是用來和Binder驅動程序進行交互的了。
**Step 11. ProcessState.startThreadPool**
這個函數定義在**frameworks/base/libs/binder/ProcessState.cpp**文件中:
~~~
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
~~~
ProcessState類是Binder進程間通信機制的一個基礎組件,它的作用可以參考[淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路](https://blog.csdn.net/luoshengyang/article/details/6627260)、[Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6629298)和[Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6633311)這三篇文章。這里它調用spawnPooledThread函數進一步處理。
**Step 12. ProcessState.spawnPooledThread**
這個函數定義在**frameworks/base/libs/binder/ProcessState.cpp**文件中:
~~~
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
char buf[32];
sprintf(buf, "Binder Thread #%d", s);
LOGV("Spawning new pooled thread, name=%s\n", buf);
sp<Thread> t = new PoolThread(isMain);
t->run(buf);
}
}
~~~
這里它會創建一個PoolThread線程類,然后執行它的run函數,最終就會執行PoolThread類的threadLoop函數了。
**Step 13. PoolThread.threadLoop**
這個函數定義在**frameworks/base/libs/binder/ProcessState.cpp**文件中:
~~~
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
~~~
這里它執行了IPCThreadState::joinThreadPool函數進一步處理。IPCThreadState也是Binder進程間通信機制的一個基礎組件,它的作用可以參考[淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路](http://blog.csdn.net/luoshengyang/article/details/6627260)、[Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6629298)和[Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6633311)這三篇文章。
**Step 14. IPCThreadState.joinThreadPool**
這個函數定義在**frameworks/base/libs/binder/IPCThreadState.cpp**文件中:
~~~
void IPCThreadState::joinThreadPool(bool isMain)
{
......
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 = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
......
result = executeCommand(cmd);
}
......
} while (result != -ECONNREFUSED && result != -EBADF);
......
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
~~~
這個函數首先告訴Binder驅動程序,這條線程要進入循環了:
~~~
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
~~~
然后在中間的while循環中通過talkWithDriver不斷與Binder驅動程序進行交互,以便獲得Client端的進程間調用:
~~~
result = talkWithDriver();
~~~
獲得了Client端的進程間調用后,就調用excuteCommand函數來處理這個請求:
~~~
result = executeCommand(cmd);
~~~
最后,線程退出時,也會告訴Binder驅動程序,它退出了,這樣Binder驅動程序就不會再在Client端的進程間調用分發給它了:
~~~
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
~~~
我們再來看看talkWithDriver函數的實現。
**Step 15. talkWithDriver**
這個函數定義在**frameworks/base/libs/binder/IPCThreadState.cpp**文件中:
~~~
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
......
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don'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_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (long unsigned int)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data();
} else {
bwr.read_size = 0;
}
......
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
......
#if defined(HAVE_ANDROID_OS)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
......
}
} while (err == -EINTR);
....
if (err >= NO_ERROR) {
if (bwr..write_consumed > 0) {
if (bwr.write_consumed < (ssize_t)mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
......
return NO_ERROR;
}
return err;
}
~~~
這個函數的具體作用可以參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文,它只要就是通過ioctl文件操作函數來和Binder驅動程序交互的了:
~~~
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
~~~
有了這個線程池之后,我們在開發Android應用程序的時候,當我們要和其它進程中進行通信時,只要定義自己的Binder對象,然后把這個Binder對象的遠程接口通過其它途徑傳給其它進程后,其它進程就可以通過這個Binder對象的遠程接口來調用我們的應用程序進程的函數了,它不像我們在C++層實現Binder進程間通信機制的Server時,必須要手動調用IPCThreadState.joinThreadPool函數來進入一個無限循環中與Binder驅動程序交互以便獲得Client端的請求,這樣就實現了我們在文章開頭處說的Android應用程序進程天然地支持Binder進程間通信機制。
細心的讀者可能會發現,從Step 1到Step 9,都是在Android應用程序框架層運行的,而從Step 10到Step 15,都是在Android系統運行時庫層運行的,這兩個層次中的Binder進程間通信機制的接口一個是用Java來實現的,而別一個是用C++來實現的,這兩者是如何協作的呢?這就是通過JNI層來實現的了,具體可以參考[Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6642463)一文。
回到Step 8中的RuntimeInit.zygoteInit函數中,在初始化完成Binder進程間通信機制的基礎設施后,它接著就要進入進程的入口函數了。
**Step 16. RuntimeInit.invokeStaticMain**
這個函數定義在**frameworks/base/core/java/com/android/internal/os/RuntimeInit.java**文件中:
~~~
public class ZygoteInit {
......
static void invokeStaticMain(ClassLoader loader,
String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = loader.loadClass(className);
} catch (ClassNotFoundException ex) {
......
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
......
} catch (SecurityException ex) {
......
}
int modifiers = m.getModifiers();
......
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
......
}
~~~
前面我們說過,這里傳進來的參數className字符串值為"android.app.ActivityThread",這里就通ClassLoader.loadClass函數將它加載到進程中:
~~~
cl = loader.loadClass(className);
~~~
然后獲得它的靜態成員函數main:
~~~
m = cl.getMethod("main", new Class[] { String[].class });
~~~
函數最后并沒有直接調用這個靜態成員函數main,而是通過拋出一個異常ZygoteInit.MethodAndArgsCaller,然后讓ZygoteInit.main函數在捕獲這個異常的時候再調用android.app.ActivityThread類的main函數。為什么要這樣做呢?注釋里面已經講得很清楚了,它是為了清理堆棧的,這樣就會讓android.app.ActivityThread類的main函數覺得自己是進程的入口函數,而事實上,在執行android.app.ActivityThread類的main函數之前,已經做了大量的工作了。
我們看看ZygoteInit.main函數在捕獲到這個異常的時候做了什么事:
~~~
public class ZygoteInit {
......
public static void main(String argv[]) {
try {
......
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
......
}
}
......
}
~~~
它執行MethodAndArgsCaller的run函數:
~~~
public class ZygoteInit {
......
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
......
} catch (InvocationTargetException ex) {
......
}
}
}
......
}
~~~
這里的成員變量mMethod和mArgs都是在前面構造異常對象時傳進來的,這里的mMethod就對應android.app.ActivityThread類的main函數了,于是最后就通過下面語句執行這個函數:
~~~
mMethod.invoke(null, new Object[] { mArgs });
~~~
這樣,android.app.ActivityThread類的main函數就被執行了。
**Step 17. ActivityThread.main**
這個函數定義在**frameworks/base/core/java/android/app/ActivityThread.java**文件中:
~~~
public final class ActivityThread {
......
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
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 = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
......
}
~~~
從這里我們可以看出,這個函數首先會在進程中創建一個ActivityThread對象:
~~~
ActivityThread thread = new ActivityThread();
~~~
然后進入消息循環中:
~~~
Looper.loop();
~~~
這樣,我們以后就可以在這個進程中啟動Activity或者Service了。
至此,Android應用程序進程啟動過程的源代碼就分析完成了,它除了指定新的進程的入口函數是ActivityThread的main函數之外,還為進程內的Binder對象提供了Binder進程間通信機制的基礎設施,由此可見,Binder進程間通信機制在Android系統中是何等的重要,而且是無處不在,想進一步學習Android系統的Binder進程間通信機制,請參考[Android進程間通信(IPC)機制Binder簡要介紹和學習計劃](http://blog.csdn.net/luoshengyang/article/details/6618363)一文。
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析