深知大多数程序员,想要提拔技能,通常是本身探索发展,但本身不成体系的自学结果低效又漫长,而且极易遇到天花板技术故步自封!
既有恰当小白学习的零基础资料,也有恰当3年以上履历的小搭档深入学习提拔的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比力多,这里只是将部门目次截图出来,全套包罗大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
必要这份体系化的资料的朋侪,可以戳这里获取
Android Q 开始,谷歌引入了cgroup抽象层,搭配使用任务设置文件,来屏蔽底层cgroup调用细节,向上提供API。cgroup抽象层编译成库libprocessgroup。抽象层通过往cgroup的文件节点写入相应的值,来触发kernel的回调。
终极kernel cgroup机制的freezer控制子体系真正实现了冰冻进程的功能。
一个进程从前台运行到被冰冻的路程
2 Framework 上层
2.1 代码路径及流程
- frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
- frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.java
- frameworks/base/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
- frameworks/base/core/java/android/os/Process.java
- frameworks/base/core/jni/android_util_Process.cpp
复制代码 2.2 OomAdjuster更新进程adj的场景
- static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
- static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
- static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
- static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
- static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
- static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
- static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
- static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
- static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
- static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
- static final String OOM_ADJ_REASON_ALLOWLIST = OOM_ADJ_REASON_METHOD + "_allowlistChange";
- static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
- static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
复制代码 通过更新原因可以看到,进程的状态变化,或者组件的状态变化会触发重新计算adj。
举例, 当一个APP处置惩罚广播时,就会触发重新计算这个APP的adj,此时的更新原因是OOM_ADJ_REASON_START_RECEIVER:
- private final void processCurBroadcastLocked(BroadcastRecord r,
- ProcessRecord app) throws RemoteException {
- ......
- r.receiver = thread.asBinder();
- r.curApp = app;
- final ProcessReceiverRecord prr = app.mReceivers;
- prr.addCurReceiver(r);
- app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
- mService.updateLruProcessLocked(app, false, null);
- // Make sure the oom adj score is updated before delivering the broadcast.
- // Force an update, even if there are other pending requests, overall it still saves time,
- // because time(updateOomAdj(N apps)) <= N * time(updateOomAdj(1 app)).
- mService.enqueueOomAdjTargetLocked(app);
- mService.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
- ......
- }
复制代码 OomAdjuster在computeOomAdjLSP中会将该app的adj提拔至FOREGROUND_APP_ADJ:
- private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
- ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
- boolean computeClients) {
- ......
- } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
- // An app that is currently receiving a broadcast also
- // counts as being in the foreground for OOM killer purposes.
- // It's placed in a sched group based on the nature of the
- // broadcast as reflected by which queue it's active in.
- adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
- ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
- state.setAdjType("broadcast");
- procState = ActivityManager.PROCESS_STATE_RECEIVER;
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
- }
- }
- ......
复制代码 2.3 Debounce time
当某个APP进程的adj达到CACHED_APP_MIN_ADJ时,CachedAppOptimizer就会调用freezeAppAsyncLSP,在debounce time之后,正式冰冻该进程, 这是为了防止进程在进入cached状态时另有任务没有完成从而间接影响用户体验。
Debounce time 在Android S 上默认是十分钟,这个值是可以在线修改的, 好比改为1秒:
- adb shell device_config put activity_manager_native_boot freeze_debounce_timeout 1000
复制代码 修改后的值重启会失效,变回默认值。
与异步冰冻流程相反,解冻的过程是同步举行的,一个App进程一旦被解冻成功,它就立刻恢复正常运行。
2.4 freezeProcess
第一步,检查文件锁"/proc/locks"的状态。这是为了防止冰冻进程持有文件锁引起死锁。思量到一些特殊场景下,进程在被冰冻的过程中拿住了文件锁,冰冻成功后还会再检查一次,发现持有锁就立刻解冻。
第二步,freeze binder。这一步禁掉该进程对同步binder请求的接收和处置惩罚,以及对异步binder请求的处置惩罚。该过程必要在100ms内成功,如果进程必要处置惩罚的请求过多导致无法完成,则再多给一轮debounce time。
第三步,setProcessFrozen,调用抽象层提供的API冰冻进程。
第四步,再次检查该进程有没有必要处置惩罚的binder请求,有则解冻进程,再多给一轮debounce time。这个检查是为一些特殊场景下,进程在被冰冻的过程中产生了binder请求。
2.5 setProcessFrozen
- void android_os_Process_setProcessFrozen( JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
- {
- bool success = true;
-
- if (freeze) {
- success = SetProcessProfiles(uid, pid, {"Frozen"});
- } else {
- success = SetProcessProfiles(uid, pid, {"Unfrozen"});
- }
-
- if (!success) {
- signalExceptionForGroupError(env, EINVAL, pid);
复制代码 调用cgroup抽象层的SetProcessProfiles, 传入参数“Frozen”。
3 cgroup 中间抽象层
cgroup中间抽象层libprocessgroup,重要提供两个功能,其一在启动阶段,根据cgroups.json 来装载具体的cgroup; 其二根据task_profiles.json来界说对cgroup具体的操作以及参数。 重要代码:
- /system/core/libprocessgroup/
复制代码 3.1 cgroups.json
示例文件:
- {
- "Cgroups": [
- {
- "Controller": "cpu",
- "Path": "/dev/cpuctl",
- "Mode": "0755",
- "UID": "system",
- "GID": "system"
- },
- {
- "Controller": "memory",
- "Path": "/dev/memcg",
- "Mode": "0700",
- "Optional": true
- }
- ],
- "Cgroups2": {
- "Path": "/sys/fs/cgroup",
- "Mode": "0755",
- "UID": "system",
- "GID": "system",
- "Controllers": [
- {
- "Controller": "freezer",
- "Path": ".",
- "Mode": "0755",
- "UID": "system",
- "GID": "system"
- }
- ]
- }
- }
复制代码 该文件分为两部门,“Cgroups” 描述cgroup v1 的控制子体系 和"Cgroups2" 描述cgroup v2的控制子体系。如果不了解cgroup 两个版本,可以参看以下网址:
www.kernel.org/doc/html/la… www.kernel.org/doc/html/la…
目前v1和v2是共存的, freezer所使用的是v2,对应根目次是/sys/fs/cgroup, UID和GID都是system。
启动阶段,Init在SetupCgroupAction中通过调用CgroupSetup,剖析cgroups.json文件,完成对cgroup的装载。
必要留意的是,cgroups.json文件大概不止一个:
- /system/core/libprocessgroup/profiles/cgroups.json //默认文件,都有
- /system/core/libprocessgroup/profiles/cgroups_<API level>.json //API级别的文件,可能有
- /vendor/xxx/cgroups.json //vendor自定义的文件
复制代码 这三个文件加载的顺序是: 默认–> API级别 --> vendor,于是就存在一个覆盖的流程。只要后面一个文件中界说的"Controller"与前面的字符串雷同,就会覆盖前者的界说。
形成的层级布局是这样的:
Android freezer 在/sys/fs/cgroup下创建了以uid/pid命名的二级子目次,对uid节点的控制会同步应用于其下面所有的pid节点。 uid在应用安装的时间确定, pid在应用使用的时间产生。如果manifest中使用了android:process,则在当前uid目次下创建一个新的pid开头的目次; 如果进程自动调用了fork产生子进程,则不会产生新的pid目次,而是放在父进程目次下,这就意味着父进程被冰冻的时间同目次的子进程也会被冰冻。
3.2 task_profiles.json
示例 task_profiles.json
- {
- "Attributes": [
- {
- "Name": "UClampLatencySensitive",
- "Controller": "cpu",
- "File": "cpu.uclamp.latency_sensitive"
- },
- {
- "Name": "FreezerState",
- "Controller": "freezer",
- "File": "cgroup.freeze"
- }
- ],
-
- "Profiles": [
- {
- "Name": "Frozen",
- "Actions": [
- {
- "Name": "SetAttribute",
- "Params":
- {
- "Name": "FreezerState",
- "Value": "1"
- }
- }
- ]
- },
- {
- "Name": "Unfrozen",
- "Actions": [
- {
- "Name": "SetAttribute",
- "Params":
- {
- "Name": "FreezerState",
- "Value": "0"
- }
- }
- ]
- },
- {
- "Name": "CpuPolicySpread",
- "Actions": [
- {
- "Name": "SetAttribute",
- "Params":
- {
- "Name": "UClampLatencySensitive",
- "Value": "1"
- }
- }
- ]
- }
- ],
-
- "AggregateProfiles": [
- {
- "Name": "SCHED_SP_BACKGROUND",
- "Profiles": [ "HighEnergySaving", "LowIoPriority", "TimerSlackHigh" ]
- }
- ]
- **深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
- ![](https://i-blog.csdnimg.cn/blog_migrate/1e210328c1ebf43f08d3b6c5f5c13b48.png)
- ![img](https://img-blog.csdnimg.cn/img_convert/b81c01078cc47958a8165730f909b09e.png)
- ![img](https://img-blog.csdnimg.cn/img_convert/8720b3d6a632247f2492e850d3daa982.png)
- **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**
- **由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
- **[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**
- sdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
- [外链图片转存中...(img-QEF5yALi-1715607349654)]
- [外链图片转存中...(img-sxCQ4f3f-1715607349655)]
- **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**
- **由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
- **[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |