Application启动流程分析一 Zygote是如何fork进程的
一个App启动另外一个App不会直接启动Application,而是启动另外一个App的MainActivity
应用进程启动
当System_service进程里面的ATMS检查到要启动的Activity对应的进程还没启动的时候,就会通过socket机制通知Zygote进程fork出对应的APP进程。
ActivityStackSupervisor类的startSpecificActivity,判断Activity对应的进程是否被启动
ActivityStackSupervisor类里面的startSpecificActivity是真正启动Activity之前执行的函数,这个函数首先判断了Activity对应的进程是否创建,创建了的话直接启动Activity,否则为app启动一个进程。
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
// 进程已经创建的话,直接启动activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
//进程不存在的话,为app启动一个进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
真正启动进程—》ATMS的startProcessAsync怎么启动一个进程?
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
try {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
+ activity.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
isTop, hostingType, activity.intent.getComponent());
mH.sendMessage(m);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
通过代码可以看到是通过ActivityManagerInternal的startProcess方法启动一个进程。ActivityManagerInternal是AMS里面的一个内部类,这个内部类里面有AMS大部分的服务。
public final class LocalService extends ActivityManagerInternal
在LocalService的startProcess方法里面最后会调入到AMS的startProcessLocked方法。
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
ProcessRecord和ProcessList
ProcessRecord记录App进程相关信息的重要类。
- 1.ApplicationInfo info:AndroidManifest.xml中定义的Application信息
2.boolean isolated:是不是isolated进程
3.int uid:进程uid
4.int userId:这个是android做的多用户系统id,就像windows可以登录很多用户一样,android 也希望可以实现类似的多用户
5.String processName:进程名字,默认情况下是包名
6.UidRecord uidRecord:记录已经使用的uid
7.IApplicationThread thread:这个很重要,它是ApplicationThread的客户端,AMS就是通过这 个对象给apk进程发送异步消息的(管理四大组件的消息),所以只有这个对象不为空的情况下, 才代表apk进程可是使用了
…
AMS管理手机里面所有App进程,AMS如何管理这一系列的ProcessRecord?尤其是正在运行的App和对应的ProcessRecord。
会有一个ProcessList类管理所有的正在运行的进程对应的ProcessRecord。
/**
* List of running applications, sorted by recent usage.
* The first entry in the list is the least recently used.
*/
//存放正在运行的app进程对应的ProcessRecord,会通过最近的使用情况来进行排序
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();// 正在运行的app进程
/**
* The currently running isolated processes.
*/
//存放正在运行的隔离的进程对应的ProcessRecord
final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
AMS通过持有ProcessList类,进而持有所有进程对应的ProcessRecord。
那么进程的优先级怎么去管理?通过ProcessList里面的mOomAdj 整形数组去设置进程优先级。
// These are the various interesting memory levels that we will give to
// the OOM killer. Note that the OOM killer only supports 6 slots, so we
// can't give it a different value for every possible kind of process.
private final int[] mOomAdj = new int[] {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
PERCEPTIBLE_LOW_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_LMK_FIRST_ADJ
};
AMS通过startProcessAsync调用到ProcessList的startProcess方法
mProcessList.startProcessLocked最后会调用到重载方法startProcessLocked通过startProcess启动进程。
@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
......
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
}
......
}
}
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
......
if (hostingRecord.usesWebviewZygote()) {
//webview进程启动
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
//隔离进程启动
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
//普通进程启动
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
......
}
Process工具类通过ZygoteProcess工具类的帮助,使用socket给Zygote发送fork进程的信息
Process类只是一个java工具类,里面的都是一些static方法。
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
public static ProcessStartResult start(@NonNull final String processClass,
@Nullable final String niceName,
int uid, int gid, @Nullable int[] gids,
int runtimeFlags,
int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
ZygoteProcess同样是一个工具类,里面也是static方法,专门提供给Process工具类,用于通过Zygote进程fork出App进程。ZygoteProcess的start最后会调用到attemptZygoteSendArgsAndGetResult方法,这个方法里面通过socket把进程的相关信息,名称,pid,target-sdk-version,package-name等发送给Zygote进程。
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
zygoteWriter.write(msgStr);
zygoteWriter.flush(); // 发送 socket信号
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt(); // 读socket 结果
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}
ZygoteServer收到fork进程的socket信息
我们都知道zygoteInit创建后,会创建一个ZygoteServer,然后执行runSelectLoop函数,这个函数开启一个死循环,不断的循环去接收Socket信息。如果有信息过来就fork出一个进程。
ZygoteServer收到socket信息后,真正执行fork的是在ZygoteConnection的processOneCommand函数里面
// Fork子进程,得到一个新的pid
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//处理子进程
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, serverPipeFd);
return null;
}
}
Zygote.forkAndSpecialize会返回两个结果(两个pid),Zygote进程中执行fork函数的地方只是这个进程的一部分,fork出两个进程后,这两个进程都会有一个正在执行的fork函数,两个进程会返回两个pid。如果返回的pid是0,说明是子进程在执行;大于0是Zygote进程;如果是-1则是fork失败。
Zygote进程fork出的孩子的进程后怎么处理
Zygote进程有一个socket服务器,fork出来的子进程也有一个socket服务器。这个socket服务器对于子进程来说是没用的,首先给他关掉。
其次调用ZygoteConnection里面的handleChildProc方法,这个方法会跑到ZygoteInit里面执行ZygoteInit方法。
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();//初始化运行环境
ZygoteInit.nativeZygoteInit();//启动Binder ,方法在 androidRuntime.cpp中注册(启动Binder驱动,启动Binder线程池)
// 通过反射创建程序入口函数的 Method 对象,并返回 Runnable 对象
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
zygoteInit函数里面首先初始化运行环境,接着调用ZygoteInit.nativeZygoteInit,这是native方法,会通过JNI去调用到app_main.cpp的onZygoteInit方法。
virtual void onZygoteInit()
{
//打开binder物理驱动,再通过mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作
//并且设置了Binder最大线程为15
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
//创建一个新的Binder线程,不断进行talkWithDriver()
proc->startThreadPool();
}
其实我们ActivityThread里面的内部类ApplicationThread就是Binder线程池里面的一个线程,所以我们通过ApplicationThread去处理各种生命周期的时候,我们要通过sendMessage发送消息给主线程,通过主线程去处理。
private class ApplicationThread extends IApplicationThread.Stub
最后会执行RuntimeInit.applicationInit方法
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
......
// startClass: 如果AMS通过socket传递过来的是 ActivityThread
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 通过反射拿到对应类的main方法的Method对象
m = cl.getMethod("main", new Class[] { String[].class });
}
......
}
static class MethodAndArgsCaller implements Runnable {
......
//调用 run 方法,执行对应类的main方法(SystemServer或者ActivityThread)
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
}
......
}
可以看到是通过反射去创建对应App进程的main函数。
为什么使用反射执行对应的main方法
因为Zygote进程不仅仅要创建App进程,还得创建Sysytem_service进程等,这个进程的main函数方法不一样。我们通过反射,全路径名称Zygote会通过socket通信传给我们,我们拿到全路径就可以直接统一反射创建对象,再反射执行对应的main函数。
原文地址:https://blog.csdn.net/qq_42426725/article/details/135911594
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!