android android:process=,Android app启动流程
進(jìn)程創(chuàng)建前
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) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
start函數(shù)里面沒(méi)有做太多的事情,直接交給了startViaZygote
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) {
ArrayList argsForZygote = new ArrayList();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
....
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
startViaZygote 函數(shù)前面都是對(duì)參數(shù)的整理。
后面交給了zygoteSendArgsAndGetResult。
但是這里我們需要注意的這邊 openZygoteSocketIfNeeded 會(huì)打開(kāi)一個(gè)socket,用于和zygote通訊,這個(gè)zygote之所以要一個(gè)abi參數(shù)因?yàn)樵?4位系統(tǒng)中有兩個(gè)zygote進(jìn)程。
root 264 1 1173156 127704 0 0000000000 S zygote64
root 265 1 934112 114496 0 0000000000 S zygote
就分別通訊的意思。
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)
throws ZygoteStartFailedEx {
try {
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
上一步拿到了zygoteState 現(xiàn)在進(jìn)行通訊,首先進(jìn)行的參數(shù)的校驗(yàn),如果沒(méi)有問(wèn)題就通過(guò)一個(gè)一個(gè)參數(shù)write傳輸過(guò)去給zygote。
zygote拿到這些參數(shù)就會(huì)給你創(chuàng)建好需要的進(jìn)程。
然后返回結(jié)果通過(guò)read讀取出來(lái)。
那么zygote那邊是怎么創(chuàng)建進(jìn)程呢?我們來(lái)看下zygote那邊的工作。
進(jìn)程的創(chuàng)建
zygote循環(huán)
zygoteInit.main()函數(shù)是zygote啟動(dòng)的時(shí)候會(huì)執(zhí)行的函數(shù),關(guān)于zygote啟動(dòng)這里不在詳細(xì)解析。
public static void main(String argv[]) {
try {
runSelectLoop(abiList);
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
在main函數(shù)中會(huì)調(diào)用。runSelectLoop開(kāi)啟socket等待。
我們這里留意下這MethodAndArgsCaller異常。
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
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();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
zygote起來(lái)以后會(huì)一直在這邊循環(huán)等待,等待你們連接我并把需要?jiǎng)?chuàng)建進(jìn)程的參數(shù)傳輸給我。有連接過(guò)來(lái)了,就會(huì)執(zhí)行runOnce函數(shù)。
runOnce
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
try {
parsedArgs = new Arguments(args);
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) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
logAndPrintError(newStderr, "Invalid zygote arguments", ex);
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
}
try {
if (pid == 0) {
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
這里關(guān)鍵的地方就是forkAndSpecialize 前面都是收集參數(shù)等待。
后forkAndSpecialize fork進(jìn)程后,父進(jìn)程和紫禁城分道揚(yáng)鑣。----這個(gè)是linux進(jìn)程創(chuàng)建的知識(shí)了
接下來(lái)我們要分開(kāi)兩條不同關(guān)注點(diǎn)去看進(jìn)程的創(chuàng)建了
---? forkAndSpecialize 會(huì)調(diào)用linux的fork系統(tǒng)調(diào)用創(chuàng)建進(jìn)程,創(chuàng)建后我們關(guān)注它的一些環(huán)境的建立。
---handleChildProc 進(jìn)程創(chuàng)建后回去加載app的入口也就是ActivityThread。我們關(guān)注它是怎去加載的。
如果是單單看應(yīng)用的啟動(dòng),往應(yīng)用層去理解呢,其實(shí)不太需要知道fork流程,如果想更深入了解系統(tǒng)的運(yùn)行機(jī)制,可以一起來(lái)看下forkAndSpecialize到底做來(lái)什么東西。
進(jìn)程的fork
上面講到forkAndSpecialize 函數(shù),我們這節(jié)的目的,看下forkAndSpecialize是怎么到底層調(diào)用linux的fork系統(tǒng)調(diào)用,從而開(kāi)辟一個(gè)進(jìn)程的。
要了解fork系統(tǒng)調(diào)用和運(yùn)用的需要去了解linux的應(yīng)用開(kāi)發(fā)。這樣才比較好了解進(jìn)程的啟動(dòng),在linux里面為什么用一個(gè)fork就創(chuàng)建了一個(gè)進(jìn)程。
這個(gè)是需要一個(gè)基礎(chǔ)知識(shí)的。
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
...
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
...
return pid;
}
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir);
我們來(lái)看到forkAndSpecialize 什么都沒(méi)有做直接交給了nativeForkAndSpecialize,而nativeForkAndSpecialize是一個(gè)jni底層的函數(shù)。
這個(gè)函數(shù)的實(shí)現(xiàn)在com_android_internal_os_Zygote.cpp (frameworks\base\core\jni)
static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
在這個(gè)com_android_internal_os_Zygote.cpp 文件里面,我們看到它的jni實(shí)現(xiàn)是com_android_internal_os_Zygote_nativeForkAndSpecialize
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
jlong capabilities = 0;
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, instructionSet, appDataDir);
}
com_android_internal_os_Zygote_nativeForkAndSpecialize 這個(gè)函數(shù)也沒(méi)有做太多的事情,直接交給了ForkAndSpecializeCommon。
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jstring instructionSet, jstring dataDir) {
SetSigChldHandler();
...
pid_t pid = fork();
if (pid == 0) {
..
if (!is_system_server) {
int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
if (rc == -EROFS) {
ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
} else {
ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
}
}
}
SetGids(env, javaGids);
...
int rc = setresgid(gid, gid, gid);
...
SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env);
...
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
...
if (se_info_c_str != NULL) {
SetThreadName(se_name_c_str);
}
...
} else if (pid > 0) {
...
}
return pid;
}
這個(gè)函數(shù)做的事情就有點(diǎn)多了,關(guān)鍵的是我們看到了fork()函數(shù)。
---在這個(gè)fork()函數(shù)之前做的是一些signal的設(shè)置
---fork()完成了以后兵分兩路,子進(jìn)程會(huì)去做很多gid 、scheduler 和 selinux等等的設(shè)置。
到這里我們就完整的看到了一個(gè)進(jìn)程創(chuàng)建的過(guò)程。返回pid。
handleChildProc
現(xiàn)在進(jìn)程出來(lái)了,我們需要一路返回,看看我們的進(jìn)程會(huì)去做那些工作,是怎么走入到我們的apk代碼里面的,主要是走到ActivityThread的過(guò)程。
我們回到handleChildProc,里面來(lái)。
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
}
我們的進(jìn)程已經(jīng)創(chuàng)建完成來(lái)。handleChildProc是首先會(huì)調(diào)用的函數(shù),而這個(gè)函數(shù)又調(diào)用來(lái)RuntimeInit.zygoteInit,為什么是講這個(gè)函數(shù)而不去講上面的函數(shù)?
我這里講一個(gè)簡(jiǎn)單的linux知識(shí)。
linux進(jìn)程創(chuàng)建也是一樣的會(huì)直接fork,fork完成后如果你要加載代碼一般是用execv系統(tǒng)調(diào)用去加載代碼的,但是Android,使用的是java虛擬機(jī)。
所以,上面的流程是給一些本地進(jìn)程走的。而java是通過(guò)Class進(jìn)行類(lèi)加載,來(lái)我們來(lái)一口氣讀完下面三個(gè)函數(shù)。
看下是怎么類(lèi)加載的。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
applicationInit(targetSdkVersion, argv, classLoader);
}
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
...
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
...
}
...
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
這里我們關(guān)注下面流程:
1. 首先設(shè)置虛擬機(jī)的環(huán)境
2. 調(diào)用invokeStaticMain
3.在invokeStaticMain,我們找到這個(gè)類(lèi)也就是ActivityThread類(lèi),這到這個(gè)類(lèi)的Method,也就是main函數(shù)。
4.最后居然沒(méi)有運(yùn)行這個(gè)類(lèi)而是拋出一個(gè)異常。很匪夷所思,根據(jù)反射調(diào)用的話,應(yīng)該是要 m.invoke(null, arg);才對(duì)的。
那么它拋出這個(gè)異常是在哪里catch的呢?
還記得文章最前面我們說(shuō)要關(guān)注的拋出的異常嗎?
在前面zygote循環(huán)的時(shí)候我說(shuō)要關(guān)注的異常。
public static void main(String argv[]) {
try {
runSelectLoop(abiList);
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
他就是在這里catch了這個(gè)異常然后調(diào)用了這個(gè)異常的run函數(shù)。
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
...
throw new RuntimeException(ex);
}
}
然后再這里進(jìn)行了invoke反射調(diào)用。
至于為什么要通過(guò)拋出異常的方法去做這個(gè)調(diào)用而不是直接調(diào)用,網(wǎng)上早有人給出了答案。這里就不多說(shuō)。
到現(xiàn)在整個(gè)進(jìn)程啟動(dòng)的流程就結(jié)束了。
ActivityThread類(lèi)加載起來(lái)以后,會(huì)和ams交互,接下來(lái)會(huì)調(diào)用到你的activity的onCreate方法,onResume方法。
然后你的apk就完美運(yùn)行了。
總結(jié)
以上是生活随笔為你收集整理的android android:process=,Android app启动流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 我国导弹有多厉害?
- 下一篇: 对计算机技术的发展方向研究,网络技术发展