程序的啓動是從進程啓動開始的,換句話說只有程序進程啓動後,程序纔會加載和執行,在AMS啓動程序時首先會判斷當前進程是否啓動,對未啓動的進程會發送請求,Zygote在收到請求後創建新的進程;
1、Zygote監聽客戶端請求
由Android進階知識樹——Android系統的啓動過程知道,系統的啓動會執行到ZygoteInit.main()方法;
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();//1
zygoteServer.registerServerSocketFromEnv(socketName);
caller = zygoteServer.runSelectLoop(abiList); //2
}
在main中創建並註冊了服務端的Socket,然後執行runSelectLoop()循環等待AMS的請求創建進程;
- registerServerSocketFromEnv()
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//1
try {
String env = System.getenv(fullSocketName);//2
fileDesc = Integer.parseInt(env);
}
try {
FileDescriptor fd = new FileDescriptor();//3
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);//4
mCloseSocketFd = true;
} catch (IOException ex) {
}
}
在registerServerSocketFromEnv中,首先使用ANDROID_SOCKET_PREFIX拼接Socket名稱,最終的名稱爲ANDROID_SOCKET_zygote,然後將fullSocketName轉換爲環境變量的值,註釋3處創建文件描述符,然後根據文件描述符創建LocalServerSocket對象
- zygoteServer.runSelectLoop()
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
177 fds.add(mServerSocket.getFileDescriptor());//1
178 peers.add(null);
179
180 while (true) { //2
181 StructPollfd[] pollFds = new StructPollfd[fds.size()];
182 for (int i = 0; i < pollFds.length; ++i) {
183 pollFds[i] = new StructPollfd();
184 pollFds[i].fd = fds.get(i);
185 pollFds[i].events = (short) POLLIN;
186 }
187 try {
188 Os.poll(pollFds, -1);
189 } catch (ErrnoException ex) {
190 throw new RuntimeException("poll failed", ex);
191 }
192 for (int i = pollFds.length - 1; i >= 0; --i) {
193 if ((pollFds[i].revents & POLLIN) == 0) {
194 continue;
195 }
197 if (i == 0) { // 3
198 ZygoteConnection newPeer = acceptCommandPeer(abiList);
199 peers.add(newPeer);
200 fds.add(newPeer.getFileDesciptor());
201 } else {
202 try {
203 ZygoteConnection connection = peers.get(i);
204 final Runnable command = connection.processOneCommand(this); // 4
205
206 if (mIsForkChild) {
213 return command;
214 } else {
223 if (connection.isClosedByPeer()) {
224 connection.closeSocket();
225 peers.remove(i);
226 fds.remove(i);
227 }
228 }
229 } catch (Exception e) {
230 if (!mIsForkChild) {
241 ZygoteConnection conn = peers.remove(i);
242 conn.closeSocket();
244 fds.remove(i);
245 } else {
250 throw e;
251 }
252 } finally {
256 mIsForkChild = false;
257 }
258 }
259 }
260 }
261 }
在runSelectLoop方法中,首先獲取註冊Socket的文件描述符fd,並將其保存在fds集合中,然後開啓循環監聽AMS的請求,在註釋3處判斷i ==0,若i=0表示Socket已連接,否則表示接收到AMS的請求信號,調用connection.processOneCommand(this)創建新的進程,創建完成後清除對應的peers集合和fds集合;
2、AMS發送創建進程請求
AMS會檢查目標程序進程,如果進程未啓動則調用startProcessLocked()方法啓動進程
int uid = app.uid; //1
......
if (ArrayUtils.isEmpty(permGids)) { //2
gids = new int[3];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
.....
final String entryPoint = "android.app.ActivityThread"; //3
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,startTime); //4
startProcessLocked執行一下邏輯:
- 獲取當前程序的uid
- 對用戶組gids創建並賦值
- entryPoint賦值爲ActivityThread的路徑,ActivityThread就是進程啓動時要初始化的類
- 調用startProcessLocked()啓動進程
在startProcessLocked()中又調用startProcess(),startProcess()中調用Process.start()方法,start中調用ZygoteProcess.startViaZygote()啓動進程,
- ZygoteProcess.startViaZygote()
private Process.ProcessStartResult startViaZygote(final String processClass,
......String[] extraArgs)throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
在startViaZygote中首先創建ArrayList集合,然後添加創建進程的啓動參數,最後調用zygoteSendArgsAndGetResult()執行啓動進程,在zygoteSendArgsAndGetResult的第一個參數中首先調用了openZygoteSocketIfNeeded()方法,它的作用其實就是連接Zygote 中服務端的Socket
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(mSocket); //1
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
if (primaryZygoteState.matches(abi)) { //2
return primaryZygoteState;
}
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(mSecondarySocket);//3
}
maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}
if (secondaryZygoteState.matches(abi)) { //4
return secondaryZygoteState;
}
}
在openZygoteSocketIfNeeded()中ZygoteState.connect()連接Zygote進程中的Socket,連接成功後返回連接的主模式,用此主模式和傳入的abi比較是否匹配,如果匹配則直接返回ZygoteState,否則連接zygote輔模式;
- zygoteSendArgsAndGetResult()
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
281 ZygoteState zygoteState, ArrayList<String> args)
282 throws ZygoteStartFailedEx {
283 try {
286 int sz = args.size();
287 for (int i = 0; i < sz; i++) {
288 if (args.get(i).indexOf('\n') >= 0) {
289 throw new ZygoteStartFailedEx("embedded newlines not allowed");
290 }
291 }
303 final BufferedWriter writer = zygoteState.writer;
304 final DataInputStream inputStream = zygoteState.inputStream;
306 writer.write(Integer.toString(args.size()));
307 writer.newLine();
309 for (int i = 0; i < sz; i++) {
310 String arg = args.get(i);
311 writer.write(arg);
312 writer.newLine();
313 }
315 writer.flush();
323 result.pid = inputStream.readInt();
324 result.usingWrapper = inputStream.readBoolean();
326 if (result.pid < 0) {
327 throw new ZygoteStartFailedEx("fork() failed");
328 }
329 return result;
330 } catch (IOException ex) {
331 zygoteState.close();
332 throw new ZygoteStartFailedEx(ex);
333 }
334 }
在zygoteSendArgsAndGetResult中獲取連接Socket返回的ZygoteState,利用ZygoteState內部的BufferedWriter將請求參數寫入Zygote進程中;
3、Zygote接收信息並創建進程
由第一部分知道,在AMS發送請求後zygote進程會接收請求,並調用ZygoteConnection.processOneCommand()方法處理請求,在ZygoteInit.main()方法中有以下代碼
final Runnable caller;
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
在runSelectLoop()中接收到AMS請求信息後,然後執行處理並返回Runnable對象並執行run()方法,
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList(); //1
descriptors = mSocket.getAncillaryFileDescriptors();
}
parsedArgs = new Arguments(args); //2
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,parsedArgs.instructionSet, parsedArgs.appDataDir);
if (pid == 0) {
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote); //3
} else {
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
}
在processOneCommand()中首先調用readArgumentList讀取參數數組,然後將數組封裝在Arguments對象中,調用Zygote.forkAndSpecialize()方法fork子進程,子進程創建成功後調用handleChildProc()初始化進程
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
}
在handleChildProc調用ZygoteInit.zygoteInit(),關於ZygoteInit.zygoteInit()方法的內容參考Android進階知識樹——Android系統的啓動過程,其最終會使用反射調用ActivityThread.main()方法,程序進入進程初始化,關於ActivityThread中的操作這裏不做分析,相信Android開發者應該瞭解;
4、啓動Binder線程池
本篇文章和上一篇Android進階知識樹——Android系統的啓動過程中都提到Binder線程池的創建,但都沒有詳細介紹,這裏補充一下,程序在啓動進程後會調用ZygoteInit.zygoteInit()方法,zygoteInit中調用本地方法nativeZygoteInit(),在ZygoteInit中聲明瞭nativeZygoteInit方法;
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();//
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
private static final native void nativeZygoteInit();
很明顯nativeZygoteInit()是JNI方法(關於JNI見另一篇文章Android進階知識樹——JNI和So庫開發),他在AndroidRuntime中完成方法動態註冊,nativeZygoteInit中對應c文件中com_android_internal_os_ZygoteInit_nativeZygoteInit()方法
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
在com_android_internal_os_ZygoteInit_nativeZygoteInit()方法中調用gCurRuntime.onZygoteInit(),這裏的gCurRuntime是AppRuntime對象,它繼承AndroidRuntime,在AndroidRuntime的構造函數中被初始化,AppRuntime類在app_main中實現
class AppRuntime : public AndroidRuntime
{
virtual void onZygoteInit() {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
}
在onZygoteInit()中調用ProcessState類的startThreadPool(),startThreadPool()中調用
void ProcessState::spawnPooledThread(bool isMain){
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
在spawnPooledThread()中使用makeBinderThreadName()生成線程名稱,然後創建PoolThread線程並執行線程
class PoolThread : public Thread{
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
PoolThread繼承Thread類,啓動PoolThread對象就創建了一個新的線程,在PoolThread的threadLoop()方法中調用IPCThreadState的joinThreadPool()方法將創建的線程加入Binder線程吃中,那麼新創建的應用進程就支持Binder進程通行了;
總結一下整個進程啓動的過程:
- AMS判斷當前進程是否啓動,對未啓動的進程發送請求
- 首先根據程序的pid設置並賦值用戶組gids
- 將entryPoint賦值爲ActivityThread的路徑,然後開始執行進程啓動
- 在與zygote交互中,首先根據設置的abi連接zygote進程中的socket,並判斷是匹配主模式還是輔模式,連接成功後返回zygoteState對象
- 使用zygoteState將請求參數寫入zygote的Socket中,zygote進程中讀取請求的信息保存在數組中
- 使用參數數組創建Argument對象,並fork出程序進程,從而啓動程序進程
- 進程啓動後調用ZygotezInit.zygoteInit()方法,內部初始化Binder線程池實現進程通信,然後反射獲取ActivityThread.main()方法,完成新進程的初始化