← 返回文章流

Android源码分析: 应用进程启动分析

Android应用进程的启动,简单来说就是从zygot进程fork出来一个新进程,并对其进行一些初始化。这样做系统的一些代码和资源等等就不需要重复加载,一些环境变量也都不需要重新设置,可以说是很巧妙的设置。下面就来具体分析一下其初始化过程。 启动时机 应用进程的启动,一般是在创建四大组件,比如说启动Activity,Service,使用ContentProvider,有广播需要处理,这些情况需要创建进程。在我们分析的代码当中,除了这几种情况,BackupAngent也会涉及到创建App进程。 启动进程调用的为AMS当中的startProcessLocked方法, 我们注意看的话,AMS当中还有另一个方法startIsolatedProcess也是用来启动进程的,但是这个方法它启动的进程一般是给系统使用的,我们这里不会分析。 AMS调用启动进程 我们就从AMS的startProcessLocked这个方法开始看起来: 1 2 3 4 5 6 7 8 9 10 11 final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */, false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */, null /* sdkSandboxClientAppPackage */, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); } 这里我们传入的参数intentFlags为0,zygotePolicyFlags为ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, allowWhileBooting为false, isolated为false。之后startProcessLocked方法内部用调用了ProcessList的同名方法,其中我们关注的核心语句如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 ProcessRecord app; ... app = getProcessRecordLocked(processName, info.uid); //从缓存中获取ProcessRecord ... if (app == null) { app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox, sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord); } else { app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); } ... final boolean success = startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride); 以上代码可以看到,会先去获取是否有现有的processRecord可用,有的话就拿出来使用,没有的话会创建新的,之后会调用startProcessLocked方法。ProcessList中使用mProcessNames来存储ProcessRecord与processName和uid的对应关系,查找的逻辑就是从map中查找不再关注。newProcessRecordLocked方法则是创建新的ProcessRecord,并且会把各种信息保存到这个record当中去。我们这里可以继续看startProcessLocked方法,,最终会调用这个方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks, String abiOverride) { //对于从缓存拿到的ProcessRecord,把原来的信息清掉 if (app.getPid() > 0 && app.getPid() != ActivityManagerService.MY_PID) { mService.removePidLocked(app.getPid(), app); app.setBindMountPending(false); app.setPid(0); app.setStartSeq(0); } app.unlinkDeathRecipient(); app.setDyingPid(0); ... final IPackageManager pm = AppGlobals.getPackageManager(); permGids pm.getPackageGids(app.info.packageName, = MATCH_DIRECT_BOOT_AUTO, app.userId); StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, app.info.packageName); //检查外部存储访问权限 externalStorageAccess = storageManagerInternal.hasExternalStorageAccess(uid, app.info.packageName); if (pm.checkPermission(Manifest.permission.INSTALL_PACKAGES, app.info.packageName, userId) == PackageManager.PERMISSION_GRANTED) { //检查安装应用的权限 Slog.i(TAG, app.info.packageName + " is exempt from freezer"); app.mOptRecord.setFreezeExempt(true); } if (app.processInfo != null && app.processInfo.deniedPermissions != null) { for (int i = app.processInfo.deniedPermissions.size() - 1; i >= 0; i--) { int[] denyGids = mService.mPackageManagerInt.getPermissionGids( app.processInfo.deniedPermissions.valueAt(i), app.userId); if (denyGids != null) { for (int gid : denyGids) { permGids = ArrayUtils.removeInt(permGids, gid); } } } } gids = computeGidsForProcess(mountExternal, uid, permGids, externalStorageAccess); //根据前面的权限和相关信息,计算新启动的进程 需要分配的用户 ... //读取app的debuggable,profileable等标志位 boolean debuggableFlag = (app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; boolean isProfileableByShell = app.info.isProfileableByShell(); boolean isProfileable = app.info.isProfileable(); if (debuggableFlag) { runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP; runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE; runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(), android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) { runtimeFlags |= Zygote.DISABLE_VERIFIER; } } if (isProfileableByShell) { runtimeFlags |= Zygote.PROFILE_FROM_SHELL; } if (isProfileable) { runtimeFlags |= Zygote.PROFILEABLE; } //把标志位信息保存到runtimeFlags中 ...//其他一些flag写入到runtimeFlags中去 if (debuggableFlag) { //debuggable时候使用wrap.sh去fork进程 String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh"; StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { if (new File(wrapperFileName).exists()) { invokeWith = "/system/bin/logwrapper " + wrapperFileName; } } finally { Stric

来自 码农明明桑作者主页
在原博客阅读全文 (新标签页打开)

以上内容来自博客订阅源,版权归原作者。关注作者后可以在 关注列表 第一时间查看作者文章。

一起聊聊 0

尊重不同观点

还没有评论。欢迎分享第一个想法。

RSS SUBSCRIPTIONS

选择 RSS 订阅

把博客汇的文章添加到你常用的阅读器。

关注文章 RSS 订阅本订阅需要登录后使用