您的位置:首页 > 汽车 > 新车 > 2023冬天11月疫情能结束吗_php和mysql网站毕业设计_竞价关键词优化软件_小红书推广方式有哪些

2023冬天11月疫情能结束吗_php和mysql网站毕业设计_竞价关键词优化软件_小红书推广方式有哪些

2024/12/25 8:51:15 来源:https://blog.csdn.net/langjian2012/article/details/144433463  浏览:    关键词:2023冬天11月疫情能结束吗_php和mysql网站毕业设计_竞价关键词优化软件_小红书推广方式有哪些
2023冬天11月疫情能结束吗_php和mysql网站毕业设计_竞价关键词优化软件_小红书推广方式有哪些

Freezer原理

Android按照优先级将一般的APP从高到低分为: 前台进程 --> 可感知进程–> 服务进程 --> Cached进程

Freezer通过冻住cached进程,来迫使这些进程让出CPU,以达到优化系统资源使用的目的。

Cached进程是怎么判定的呢?

由于android的进程的adj是会根据不同的运行状态,会动态计算的。当adj大于等于CACHED_APP_MIN_ADJ(900)

整个流程是比较清晰的,在fwk的系统服务中,会计算ADJ的变化,当满足条件后就会调用cgroup hal提供的freeze的接口,设置crashed进程的状态为freeze 

Freeze实现

下面列出下整个流程最主要的几部分代码

1)Framework层

当进程发生了以下变化后,AMS就会触发OomAdjuster.java 中的 updateOomAdjLocked 函数。

    static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";   //触发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";updateOomAdjLocked -》 updateOomAdjLSP -》 performUpdateOomAdjLSP 基本的传参和判断,不展开了。@GuardedBy({"mService", "mProcLock"})private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp,ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,boolean startProfiling) {......if (size > 0) {mAdjSeq--;// Update these reachable processesupdateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);	//更新新的ADJ} else if (state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {// In case the app goes from non-cached to cached but it doesn't have other reachable// processes, its adj could be still unknown as of now, assign one.processes.add(app);assignCachedAdjIfNecessary(processes);applyOomAdjLSP(app, false, SystemClock.uptimeMillis(),		//如果SystemClock.elapsedRealtime());}mTmpProcessList.clear();mService.mOomAdjProfiler.oomAdjEnded();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);return true;......}@GuardedBy({"mService", "mProcLock"})private void updateAppFreezeStateLSP(ProcessRecord app) {if (!mCachedAppOptimizer.useFreezer()) {return;}if (app.mOptRecord.isFreezeExempt()) {return;}final ProcessCachedOptimizerRecord opt = app.mOptRecord;// if an app is already frozen and shouldNotFreeze becomes true, immediately unfreezeif (opt.isFrozen() && opt.shouldNotFreeze()) {mCachedAppOptimizer.unfreezeAppLSP(app);return;}final ProcessStateRecord state = app.mState;// Use current adjustment when freezing, set adjustment when unfreezing.if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()	//根据当前的ADJ,frozen的状态等,设置进入还是退出frozen状态&& !opt.shouldNotFreeze()) {mCachedAppOptimizer.freezeAppAsyncLSP(app);} else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {mCachedAppOptimizer.unfreezeAppLSP(app);}}

2)Native层

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"});		//根据Frozen的字符串,去 task_profiles.json 查找对应的设备节点,最终设置 /sys/fs/cgroup/<UID_xxx>/<PID_xxx>/cgroup.freeze } else {success = SetProcessProfiles(uid, pid, {"Unfrozen"});}if (!success) {signalExceptionForGroupError(env, EINVAL, pid);}
}

3)Kernel层

Kernel的设备节点会通过定义write函数,回调到相关的定义函数,这样就能看到具体的实现代码

{.name = "cgroup.freeze",		 //cgroup_freeze_show文件 触发write函数,执行cgroup_freeze_write函数。.flags = CFTYPE_NOT_ON_ROOT,.seq_show = cgroup_freeze_show,   .write = cgroup_freeze_write,    
},freezer.c 最终会调用到 freezer中的 cgroup_do_freeze 函数
/** Freeze or unfreeze all tasks in the given cgroup.*/
static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze)
{struct css_task_iter it;struct task_struct *task;lockdep_assert_held(&cgroup_mutex);spin_lock_irq(&css_set_lock);if (freeze)set_bit(CGRP_FREEZE, &cgrp->flags);   //往设备节点写入值elseclear_bit(CGRP_FREEZE, &cgrp->flags);spin_unlock_irq(&css_set_lock);if (freeze)TRACE_CGROUP_PATH(freeze, cgrp);   elseTRACE_CGROUP_PATH(unfreeze, cgrp);css_task_iter_start(&cgrp->self, 0, &it);while ((task = css_task_iter_next(&it))) {/** Ignore kernel threads here. Freezing cgroups containing* kthreads isn't supported.*/if (task->flags & PF_KTHREAD)  //忽略 kernel进程continue;cgroup_freeze_task(task, freeze);  //把状态加入task中}css_task_iter_end(&it);/** Cgroup state should be revisited here to cover empty leaf cgroups* and cgroups which descendants are already in the desired state.*/spin_lock_irq(&css_set_lock);if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)cgroup_update_frozen(cgrp);spin_unlock_irq(&css_set_lock);
}

Freeze 项目中遇到问题:

1)进程在unfreeze的时候被system 主动kill了

被kill的原因根据根据错误提示很容易找到,相关代码也比较好理解

int freezeInfo = getBinderFreezeInfo(pid);   //从binder驱动读取在freezed的状态下的状态
//下面的判断会在unfreeze之前是否有同步的binder通信请求,如果有就会杀死进程,其因为无法清除binder驱动中的堆积信息,会引起内存泄露。
//异步的binder通信也是可以被接受,并被保存在binder驱动的buffer中,但是也会存在buffer满的问题,同样也要注意此类问题。
if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {Slog.d(TAG_AM, "pid " + pid + " " + app.processName+ " received sync transactions while frozen, killing");app.killLocked("Sync transaction while in frozen state",ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_FREEZER_BINDER_TRANSACTION, true);processKilled = true;
}

此问题在那些非persisit的进程上遇到过几次,比如多媒体中心。引起的问题也都是因为注册过capservice的回调,在后台的情况下有回调过来。

解决方案:把服务变成前台服务,或者有UI界面退出后,取消注册可能被回调的接口。

2)STR后第一次打开应用会闪退,再次打开恢复

APP退出后台并进入了freezon在状态,是可以接受oneway的消息,但是会堆积在kernel的buffer中,但是在超过50%后,就会分配不出内存。

当再发起oneway消息后binder驱动就会直接返回 BR_DEAD_REPLY。不同的client会有不同的处理方式,systemservice的处理方式大部分均为kill相关进程。

主要代码如下

	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,  //每次有binder通信后会分配对应内存快tr->offsets_size, extra_buffers_size,!reply && (t->flags & TF_ONE_WAY), current->tgid);if (IS_ERR(t->buffer)) {  //在已经分配512KB后就不能正常分配,会走进此判断/** -ESRCH indicates VMA cleared. The target is dying.*/return_error_param = PTR_ERR(t->buffer);return_error = return_error_param == -ESRCH ?BR_DEAD_REPLY : BR_FAILED_REPLY;   //会返回 BR_DEAD_REPLY 给到client端。return_error_line = __LINE__;t->buffer = NULL;goto err_binder_alloc_buf_failed;}

此问题并不会让进程直接crash,而是在后续发起其他binder通信的情况下才会出现,比如startactivty或者sendboardcast之类的消息。

解决方案:解决方案如问题1的方式,退出后需要自行unregiest相关注册,如果一定要监听某些状态,则可以启动一个前台服务来监听相关进程。此种用法也符合google的用法规则

Freezer问题调试命令

1)修改进frezon的时间,改为1秒,方便测试frezon后的状态是否Ok

adb shell device_config put activity_manager_native_boot freeze_debounce_timeout 100
2)关闭打开freezer功能,需要重启才能生效

adb shell settings put global cached_apps_freezer <enabled|disabled|default>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com