当前位置: 首页 > news >正文

厦门淘宝网站设计公司如何让网站被百度收录

厦门淘宝网站设计公司,如何让网站被百度收录,二手车网站html模板,信息科技公司网站怎么做该系列文章总纲链接#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 说明#xff1a; 说明#xff1a;本章节主要解读AMS 进程方面的知识。关注思维导图中左上侧部分即可。 我们本章节主要是对Android进程管理相关知识有一个基本的了解。先来了解下L…该系列文章总纲链接专题总纲目录 Android Framework 总纲 本章关键点总结 说明 说明本章节主要解读AMS 进程方面的知识。关注思维导图中左上侧部分即可。 我们本章节主要是对Android进程管理相关知识有一个基本的了解。先来了解下Linux的进程管理基于此我们再谈Android的进程管理体系。最后了解AMS中2个关键的进程管理APIupdateLruProcessLocked 和 updateOomAdjLocked。 1 Linux的进程管理 Linux的进程调度是操作系统核心功能之一它负责决定哪个进程在何时运行以及运行多长时间。以下是Linux进程调度的基本机制以及setpriority和sched_setscheduler两个方法的详细解读。 1.1 Linux进程调度简要解读 Linux进程调度基本机制解读如下 调度器SchedulerLinux使用调度器来决定进程的执行顺序。调度器根据进程的优先级和调度策略来选择下一个要执行的进程。调度策略Scheduling PoliciesLinux支持多种调度策略包括SCHED_NORMAL普通、SCHED_FIFO先进先出、SCHED_RR时间片轮转、SCHED_BATCH批处理和SCHED_IDLE空闲等。优先级Priority每个调度策略都有自己的优先级范围。进程的优先级越低数值越小它被调度执行的优先级就越高。时间片Time Slice在SCHED_RR和SCHED_NORMAL策略下进程被分配一个时间片即它在被抢占前可以运行的时间。上下文切换Context Switching当一个进程的时间片用完或者它主动放弃CPU时会发生上下文切换调度器会选择另一个进程来执行。 1.2 setpriority 系统调用 setpriority系统调用用于设置进程的静态优先级。这个优先级是在进程创建时分配的并且通常不会改变除非显式地调用setpriority。API详细解读如下 int setpriority(int which, int who, int value); hich指定要设置的优先级类型可以是PRIO_PROCESS进程、PRIO_PGRP进程组或PRIO_USER用户。who指定要设置优先级的进程ID、进程组ID或用户ID。value指定新的优先级值值越小优先级越高。 接下来我们来看看setpriority具体的使用方法demo如下 #include sys/resource.h #include stdio.hint main() {// 设置当前进程的nice值值越小优先级越高int result setpriority(PRIO_PROCESS, getpid(), -10);if (result -1) {perror(setpriority);return 1;}printf(Priority set to: %d\n, getpriority(PRIO_PROCESS, getpid()));return 0; } 这个程序将当前进程的nice值设置为-10这通常会提高进程的优先级。getpriority函数用于获取当前进程的优先级以验证setpriority是否成功。 1.3 sched_setscheduler 系统调用 sched_setscheduler系统调用用于设置进程的动态调度策略和相关参数。API详细解读如下 struct sched_param {int sched_priority; /* Process execution priority */ };int sched_setscheduler(pid_t pid, const struct sched_param *param); pid指定要设置调度策略的进程ID。如果pid是0则设置调用进程的调度策略。param指向sched_param结构的指针该结构包含了新的调度参数如优先级。 接下来我们来看看sched_setscheduler具体的使用方法demo如下 #include sched.h #include stdio.h #include unistd.hint main() {// 定义调度参数结构体struct sched_param param;param.sched_priority 1; // 设置优先级为1// 设置调度策略为SCHED_FIFOint policy SCHED_FIFO;int result sched_setscheduler(0, policy, param);if (result -1) {perror(sched_setscheduler);return 1;}printf(Scheduler set to: %d\n, policy);printf(Priority set to: %d\n, param.sched_priority);// 让进程睡眠一段时间以便观察调度效果sleep(10);return 0; } 这个程序将当前进程的调度策略设置为SCHED_FIFO并设置优先级为1。sched_setscheduler函数的第一个参数是0表示设置调用进程的调度策略。policy变量指定了新的调度策略param结构体指定了调度参数。 注意事项解读 在使用sched_setscheduler时需要确保进程有适当的权限通常是root权限因为改变进程的调度策略可能需要管理员权限。setpriority和sched_setscheduler的使用可能会受到操作系统安全策略的限制特别是在生产环境中。这些调用的行为可能会因不同的Linux发行版和内核配置而异。 总结setpriority和sched_setscheduler是Linux进程调度中两个重要的系统调用。setpriority用于设置进程的静态优先级而sched_setscheduler用于设置进程的动态调度策略和优先级。这两个调用共同决定了进程的调度行为允许操作系统和应用程序精细控制进程的执行顺序和优先级。通过合理配置这些参数可以优化系统性能确保关键任务的及时响应。 2 Android进程解读 2.1 Android进程分类 Android进程管理和Linux进程管理之间的关系是密切的因为Android系统是建立在Linux内核之上的。在Android中进程的分类和管理与Linux中有许多相似之处但也做了一些特定的优化和扩展以适应移动设备的特点。以下是Android进程分类的核心调用和它们与Linux进程管理的对应关系 前台进程Foreground Processes在Linux中前台进程通常是指那些与用户直接交互的进程。在Android中前台进程包括正在运行的Activity和正在执行的BroadcastReceiver。这些进程因为与用户直接交互所以系统会优先保持它们的运行。可见进程Visible Processes可见进程在Android中是指那些对用户可见但不在前台的进程例如用户最近查看的Activity。Linux中没有直接对应的概念但可以通过进程的可见性来进行类比。服务进程Service Processes在Android中服务进程是指那些运行Service组件的进程。这些服务可能在后台执行任务但对应用程序的行为至关重要。Linux中服务通常作为守护进程运行与Android中的服务进程概念相似。后台进程Background Processes后台进程在Android中是指那些对用户不可见的Activity所在的进程。这些进程可能会被系统根据需要终止以释放内存。在Linux中后台进程通常是指那些在后台运行的进程如守护进程。空进程Empty Processes空进程在Android中是指那些不包含任何活跃组件的进程但可能因为某些原因如服务绑定而保留在内存中。Linux中没有直接对应的概念但可以通过进程的资源占用来进行类比。 在Android中进程的创建和管理是通过ActivityManagerService来协调的而在Linux中进程的创建和管理是通过内核的调度器和系统调用如fork、exec、exit来实现的。Android在Linux的基础上增加了一些特定的管理机制如进程的分类和优先级管理以及与应用程序组件生命周期相关的进程管理策略。这些机制使得Android能够有效地管理有限的资源并提供良好的用户体验。 2.2 进程调度相关API 在Android Framework中Process.java文件提供了多个与进程调度相关的API。以下是一些最关键的API public class Process {private static final String LOG_TAG Process;//.../*** 设置当前线程的优先级。* * param priority 要设置的优先级值值越小优先级越高。* throws IllegalArgumentException 如果优先级值不在合法范围内。* throws SecurityException 如果当前进程没有权限设置线程优先级。*/public static final native void setThreadPriority(int priority)throws IllegalArgumentException, SecurityException;/*** 设置指定线程的优先级。* * param tid 目标线程的ID。* param priority 要设置的优先级值值越小优先级越高。* throws IllegalArgumentException 如果优先级值不在合法范围内或线程ID无效。* throws SecurityException 如果当前进程没有权限设置指定线程的优先级。*/public static final native void setThreadPriority(int tid, int priority)throws IllegalArgumentException, SecurityException;/*** 获取指定线程的优先级。* * param tid 目标线程的ID。* return 线程的当前优先级值。* throws IllegalArgumentException 如果线程ID无效。*/public static final native int getThreadPriority(int tid)throws IllegalArgumentException;/*** 将线程分组到一个线程组。* * param tid 目标线程的ID。* param group 线程组的ID。* throws IllegalArgumentException 如果线程ID或线程组ID无效。* throws SecurityException 如果当前进程没有权限更改线程组。*/public static final native void setThreadGroup(int tid, int group)throws IllegalArgumentException, SecurityException;/*** 将进程分组到一个进程组。* * param pid 目标进程的ID。* param group 进程组的ID。* throws IllegalArgumentException 如果进程ID或进程组ID无效。* throws SecurityException 如果当前进程没有权限更改进程组。*/public static final native void setProcessGroup(int pid, int group)throws IllegalArgumentException, SecurityException;/*** 获取进程所在的进程组ID。* * param pid 目标进程的ID。* return 进程所在的进程组ID。* throws IllegalArgumentException 如果进程ID无效。*/public static final native int getProcessGroup(int pid)throws IllegalArgumentException;//... } 这些native方法提供了对Android进程和线程调度参数的控制它们通过JNIJava Native Interface与底层的C/C代码交互最终调用Linux内核的系统调用来实现具体的调度策略。API解读如下 setThreadPriority(int priority)这个方法用于设置当前线程的优先级。在Android中线程优先级的范围通常是-20最高到19最低。setThreadPriority(int tid, int priority)这个方法用于设置指定线程的优先级。tid参数指定了目标线程的ID。getThreadPriority(int tid)这个方法用于获取指定线程的优先级。tid参数指定了目标线程的ID。setThreadGroup(int tid, int group)这个方法用于将线程分组到一个线程组。在Linux中线程组通常用于调度和资源管理。setProcessGroup(int pid, int group)这个方法用于将进程分组到一个进程组。在Linux中进程组通常用于调度和资源管理。getProcessGroup(int pid)这个方法用于获取进程所在的进程组ID。pid参数指定了目标进程的ID。 这些方法的使用需要相应的权限特别是在修改其他进程的调度策略时通常需要系统权限或者root权限。通过合理使用这些API开发者可以优化应用的性能和响应速度或者在特定场景下对系统资源进行更精细的控制。 2.3 Android进程关键变量解读 在Android系统中OOM_ADJ和LRU是两个关键的进程管理参数因为它们共同决定了Android系统中进程的内存分配和回收策略具体如下 内存管理OOM_ADJ和LRU帮助系统在内存不足时决定哪些进程可以被牺牲以释放内存资源。这对于保持系统稳定性和响应性至关重要尤其是在内存资源有限的移动设备上。进程优先级通过调整OOM_ADJ值系统可以为不同类型的进程设置不同的优先级确保关键任务如前台应用获得足够的资源而后台或不常用的进程则可以被适当地牺牲。性能优化合理使用LRU和OOM_ADJ可以提高应用的启动速度和响应性因为系统可以更快地从缓存中恢复进程而不是每次都从头开始启动进程。资源平衡这两个参数使得系统能够在保证用户体验的同时合理分配有限的资源平衡不同应用和进程的需求。 可见它们直接影响系统的内存管理和进程调度策略对于优化系统性能和用户体验具有重要意义。 2.3.1 OOM_ADJ的解读 OOM_ADJOut-Of-Memory AdjustmentOOM_ADJ值是一个整数用来表示进程的优先级特别是在系统内存不足时决定哪些进程可以被杀死以回收内存。OOM_ADJ值的设计目的和设计意义如下 设计目的OOM_ADJ值的主要目的是为了在系统内存不足时能够根据进程的重要性进行合理的内存回收。系统会优先杀死那些对用户体验影响较小的进程保护前台进程和对用户体验至关重要的后台进程。设计意义OOM_ADJ值有助于提高Android设备的用户体验和系统稳定性。它允许系统在面临内存压力时根据进程的重要性做出合理的决策从而在保证用户体验的同时也确保系统的流畅运行。 在Android中OOM_ADJ值的范围通常是从-1000到1000其中-1000表示最高优先级最不容易被杀死而1000表示最低优先级最容易被杀死。OOM_ADJ的值定义在ProcessList.java中代码实现如下 final class ProcessList {// 应用崩溃间隔的最短时间用于判断应用是否不稳定如果是则停止其服务并拒绝广播。static final int MIN_CRASH_INTERVAL 60 * 1000;// 处于不同状态的进程的OOMOut Of Memory调整值// 在某些地方使用我们还不确定具体的值。// 通常是要被缓存的值但我们还不知道缓存范围中的确切值。static final int UNKNOWN_ADJ 16;// 只托管不可见活动的进程可以在不造成任何干扰的情况下杀死。static final int CACHED_APP_MAX_ADJ 15;static final int CACHED_APP_MIN_ADJ 9;// 服务B列表的调整值——这些是旧的、不受欢迎的服务不像A列表中的服务那样吸引人。static final int SERVICE_B_ADJ 8;// 这是用户之前所在的应用进程。这个进程被保持在较高优先级因为用户经常会切换回之前的应用。// 这对于最近任务切换在两个最近的应用程序之间切换和正常UI流程例如在电子邮件应用中点击一个URI在浏览器中查看然后按返回键回到电子邮件都很重要。static final int PREVIOUS_APP_ADJ 7;// 这是托管Home应用的进程——我们希望尽量避免杀死它即使它通常在后台因为用户与之交互很多。static final int HOME_APP_ADJ 6;// 这是托管应用服务的进程——杀死它对用户的影响不大。static final int SERVICE_ADJ 5;// 这是一个托管重量级应用的进程。它在后台但我们希望尽量避免杀死它。值在系统启动时在system/rootdir/init.rc中设置。static final int HEAVY_WEIGHT_APP_ADJ 4;// 这是一个当前托管备份操作的进程。杀死它不是完全致命的但通常是一个坏主意。static final int BACKUP_APP_ADJ 3;// 这是一个只托管对用户可感知的组件的进程我们真的希望避免杀死它们但它们不是立即可见的。一个例子是后台音乐播放。static final int PERCEPTIBLE_APP_ADJ 2;// 这是一个只托管对用户可见的活动的进程所以我们希望它们不要消失。static final int VISIBLE_APP_ADJ 1;// 这是运行当前前台应用的进程。我们真的不想杀死它static final int FOREGROUND_APP_ADJ 0;// 这个进程被系统或持久进程绑定并表示它很重要。static final int PERSISTENT_SERVICE_ADJ -11;// 这是一个系统持久进程如电话进程。肯定不想杀死它但如果这样做了也不是完全致命的。static final int PERSISTENT_PROC_ADJ -12;// 系统进程以默认的调整值运行。static final int SYSTEM_ADJ -16;// 特殊代码用于没有被系统管理的本地进程所以没有被系统分配oom调整值。static final int NATIVE_ADJ -17;//...// 这些是我们要提供给OOM killer的各种内存级别。// 注意OOM killer只支持6个插槽所以我们不能为每种可能的进程类型提供不同的值。private final int[] mOomAdj new int[] {FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ};// 这些是低端OOM级别限制。这适用于HVGA或更小屏幕的手机内存少于512MB。// 值以KB为单位。private final int[] mOomMinFreeLow new int[] {12288, 18432, 24576,36864, 43008, 49152};// 这些是高端OOM级别限制。这适用于1280x800或更大屏幕大约有1GB RAM。// 值以KB为单位。private final int[] mOomMinFreeHigh new int[] {73728, 92160, 110592,129024, 147456, 184320}; } 这些常量代表了Android系统中不同类型进程的OOM内存不足时的杀进程调整值。这些值用于确定进程被系统杀死的优先级值越小表示优先级越高越不容易被系统杀死。这些调整值帮助系统在内存不足时决定哪些进程可以被牺牲以释放内存。用于更新oom_adj的方法为updateOomAdjLocked。 2.3.2 LRU相关变量解读 LRULeast Recently UsedLRU是最近最少使用算法核心思想是当缓存满时优先淘汰那些近期最少使用的缓存对象如果一个数据最近被访问过那么它在未来被访问的概率更高相反如果一个数据长时间未被访问那么它在未来被访问的概率较低有效避免了OOM的出现。 lruWeight是一个用于衡量进程在最近最少使用LRU列表中排序权重的参数。它通常与进程的最后活动时间或其他活动相关的因素相关联用于确定进程在LRU列表中的位置。lruWeight值的设计目的和设计意义如下 设计目的lruWeight的设计目的是为了在系统内存不足时根据进程的最近使用情况来决定哪些进程可以被优先杀死以释放内存。它帮助系统维护一个有序的进程列表确保最近被使用的进程保持在内存中而长时间未被使用的进程则可以被牺牲。设计意义lruWeight的设计意义在于优化内存资源的分配和回收。通过动态调整进程的lruWeight值系统能够更智能地管理内存提高内存使用效率。这不仅有助于提升用户体验比如通过快速恢复最近使用的应用程序还能在内存紧张时减少系统的卡顿或崩溃。 lruWeight与OOM调整值的关系lruWeight与进程的OOM调整值OOM_ADJ紧密相关因为它们共同决定了进程在内存不足时的生存概率。一个进程的lruWeight值越高其OOM调整值可能越低表示它越容易被系统杀死。 此外lruWeight还考虑了进程的类型和服务状态比如活动、服务和内容提供者这使得系统能够根据进程的实际作用和重要性来调整其在LRU列表中的位置进一步优化内存管理。 lruWeight是Android系统中一个关键的内存管理参数它通过反映进程的活跃度和重要性来帮助系统在有限的资源下做出合理的内存分配和回收决策。在Android中LRU算法常用于内存缓存和硬盘缓存的管理。用于更新LRU的方法为updateLruProcessLocked。 3 AMS 进程管理相关函数分析 基于OOM_ADJ和LRU是两个关键的进程管理参数这里我们主要探讨更新OOM_ADJ和LRU的方法。这里以startProcessLocked方法启动一个新进程为例启动相关的代码可参考文章 Android Framework AMS04startActivity分析-1(am启动到ActivityThread启动) Android Framework AMS05startActivity分析-2(ActivityThread启动到Activity拉起) 这里我们主要从AMS的attachApplicationLocked方法入手进行分析。代码实现如下 //AMSprivate final boolean attachApplicationLocked(IApplicationThread thread,int pid) {ProcessRecord app;//...try {//...// 将应用程序线程与应用程序信息绑定thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());// 更新进程的LRU列表updateLruProcessLocked(app, false, null);//...} catch (Exception e) {//...}// 如果没有执行任何操作则更新OOM调整值if (!didSomething) {updateOomAdjLocked();}return true;} 这里开始就已经调用了2个重要函数updateLruProcessLocked和updateOomAdjLocked。接下来对这2个方法进行更详细的解读。 3.1 updateLruProcessLocked分析 updateLruProcessLocked的代码实现如下所示 //AMSfinal void updateLruProcessLocked(ProcessRecord app, boolean activityChange,ProcessRecord client) {// 检查进程是否有activityfinal boolean hasActivity app.activities.size() 0 || app.hasClientActivities|| app.treatLikeActivity;// 检查进程是否有服务final boolean hasService false;// 如果没有activity变化且进程有activity则直接返回if (!activityChange hasActivity) {return;}// 更新LRU序列号mLruSeq;final long now SystemClock.uptimeMillis(); // 获取当前时间app.lastActivityTime now; // 更新进程的最后activity时间// 如果进程有activity检查它是否已经在LRU列表的最后if (hasActivity) {final int N mLruProcesses.size();if (N 0 mLruProcesses.get(N - 1) app) {return; // 如果进程已经是最后一个直接返回}} else {// 如果进程没有activity检查它是否在服务启动列表中if (mLruProcessServiceStart 0 mLruProcesses.get(mLruProcessServiceStart - 1) app) {return; // 如果进程在服务启动列表中直接返回}}// 查找进程在LRU列表中的索引int lrui mLruProcesses.lastIndexOf(app);//...// 如果进程在LRU列表中移除它if (lrui 0) {if (lrui mLruProcessActivityStart) {mLruProcessActivityStart--; // 更新activity进程起始索引}if (lrui mLruProcessServiceStart) {mLruProcessServiceStart--; // 更新服务进程起始索引}mLruProcesses.remove(lrui); // 从LRU列表中移除进程}int nextIndex;// 如果进程有activity添加到LRU列表if (hasActivity) {final int N mLruProcesses.size();if (app.activities.size() 0 mLruProcessActivityStart (N - 1)) {mLruProcesses.add(N - 1, app); // 将进程添加到LRU列表的倒数第二个位置final int uid app.info.uid;for (int i N - 2; i mLruProcessActivityStart; i--) {ProcessRecord subProc mLruProcesses.get(i);if (subProc.info.uid uid) {if (mLruProcesses.get(i - 1).info.uid ! uid) {// 交换进程位置ProcessRecord tmp mLruProcesses.get(i);mLruProcesses.set(i, mLruProcesses.get(i - 1));mLruProcesses.set(i - 1, tmp);i--;}} else {break; // 如果UID不同停止交换}}} else {mLruProcesses.add(app); // 直接添加进程到LRU列表}nextIndex mLruProcessServiceStart; // 设置下一个索引} else if (hasService) {// 如果进程有service添加到LRU列表的activity起始位置mLruProcesses.add(mLruProcessActivityStart, app);nextIndex mLruProcessServiceStart;mLruProcessActivityStart;} else {// 处理没有activity和service的进程int index mLruProcessServiceStart;if (client ! null) {int clientIndex mLruProcesses.lastIndexOf(client);if (clientIndex lrui) {clientIndex lrui; // 确保clientIndex不小于lrui}if (clientIndex 0 index clientIndex) {index clientIndex; // 更新索引}}mLruProcesses.add(index, app); // 在指定索引添加进程nextIndex index - 1; // 更新下一个索引mLruProcessActivityStart;mLruProcessServiceStart;}// 更新与进程连接的服务的LRU状态for (int j app.connections.size() - 1; j 0; j--) {ConnectionRecord cr app.connections.valueAt(j);if (cr.binding ! null !cr.serviceDead cr.binding.service ! null cr.binding.service.app ! null cr.binding.service.app.lruSeq ! mLruSeq !cr.binding.service.app.persistent) {nextIndex updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,service connection, cr, app);}}// 更新与进程相关的内容提供者的LRU状态for (int j app.conProviders.size() - 1; j 0; j--) {ContentProviderRecord cpr app.conProviders.get(j).provider;if (cpr.proc ! null cpr.proc.lruSeq ! mLruSeq !cpr.proc.persistent) {nextIndex updateLruProcessInternalLocked(cpr.proc, now, nextIndex,provider reference, cpr, app);}}} updateLruProcessLocked方法的主要目的是更新特定进程在LRU列表中的位置基于进程的活动状态如是否有活动或服务。如果进程有活动Activity则不会移动该进程在LRU列表中的位置因为活动进程应该被优先保留。如果进程没有活动但有服务连接或内容提供者引用该方法会调整这些进程在LRU列表中的位置以反映它们的使用情况。通过mLruSeq序列号控制更新确保只有在进程状态发生变化时才进行更新减少不必要的列表操作。 在updateLruProcessLocked方法中调整的具体是mLruProcesses这个关键变量。mLruProcesses是一个列表它存储了系统中所有进程的最近最少使用LRU顺序。以下是对这个方法中涉及的关键变量和操作的分析 mLruProcesses这是一个列表包含了系统中所有进程的ProcessRecord对象按照它们的最近使用情况排序。列表的前端即索引较小的位置存放最近使用的进程而列表的后端即索引较大的位置存放最少使用的进程。app.lastActivityTime每个ProcessRecord对象中的lastActivityTime字段被更新为当前时间这表示进程最后一次活跃的时间。这个字段用于确定进程在LRU列表中的位置。mLruProcessActivityStart和mLruProcessServiceStart这两个变量分别标记了LRU列表中活动进程和服务进程的起始索引。它们用于区分不同类型的进程并在添加进程到LRU列表时确定正确的位置。mLruSeqmLruSeq是一个序列号每次调用updateLruProcessLocked方法时增加用于标识LRU列表的更新周期。 在方法中执行的操作包括 更新进程的最后活动时间通过设置app.lastActivityTime为当前时间来更新。检查进程是否有活动如果进程有活动hasActivity并且没有活动变化!activityChange则不进行进一步操作。移除和添加进程如果进程在LRU列表中的位置发生变化它会从当前位置移除并根据其活动状态被重新添加到LRU列表的适当位置。更新服务和内容提供者的LRU状态对于与进程连接的服务和内容提供者它们在LRU列表中的位置也可能需要更新这是通过调用updateLruProcessInternalLocked方法实现的。 总结来说updateLruProcessLocked方法通过直接操作mLruProcesses列表和相关索引变量来管理进程的LRU顺序确保列表反映了进程的最新使用情况。这种方法有助于系统在内存不足时决定哪些进程可以被优先杀死。 这里最后在处理service和ContentProcider时调用了updateLruProcessInternalLocked方法它的代码实现如下所示 //AMSprivate int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,String what, Object obj, ProcessRecord srcApp) {// 更新进程的最后活动时间app.lastActivityTime now;// 如果进程有活动不更新其在LRU列表中的位置if (app.activities.size() 0) {return index; // 不处理包含活动的进程}// 查找进程在LRU列表中的索引int lrui mLruProcesses.lastIndexOf(app);// 如果进程不在LRU列表中记录错误并返回if (lrui 0) {return index;}// 如果进程在LRU列表中的位置已经小于或等于目标索引不更新位置if (lrui index) {return index; // 不使依赖进程在列表中向后移动}// 如果进程在活动进程的起始索引之后不更新其位置if (lrui mLruProcessActivityStart) {return index; // 不处理包含活动的进程}// 从当前位置移除进程mLruProcesses.remove(lrui);// 如果目标索引大于0将其减1if (index 0) {index--;}// 在目标索引位置添加进程mLruProcesses.add(index, app);// 返回更新后的目标索引return index;} updateLruProcessInternalLocked方法用于在LRU列表中移动依赖进程即那些没有直接用户交互但被其他进程依赖的进程。如果依赖进程没有活动并且不在活动进程的起始索引之后该方法会将这些进程向前移动以确保它们不会被错误地视为最近最少使用的进程。该方法确保依赖进程不会移动到活动进程之后从而避免降低它们的优先级。如果依赖进程不在LRU列表中该方法会记录错误并保持列表不变。 总体来说updateLruProcessLocked负责处理进程的直接状态变化而updateLruProcessInternalLocked负责处理由这些变化引起的依赖进程的间接影响。通过精确控制进程在LRU列表中的位置这两个方法帮助系统优化内存管理确保在内存不足时能够优先杀死那些最近最少使用的进程同时保护前台进程和关键后台进程。 3.2 updateOomAdjLocked分析 updateOomAdjLocked的代码较长这里分成2个部分进行解读。 3.2.1 updateOomAdjLocked前半段代码解读 updateOomAdjLocked前半段代码实现如下所示 final void updateOomAdjLocked() {// 获取当前前台活动的Activity和对应的进程记录final ActivityRecord TOP_ACT resumedAppLocked();final ProcessRecord TOP_APP TOP_ACT ! null ? TOP_ACT.app : null;// 获取当前时间用于计算时间差final long now SystemClock.uptimeMillis();// 计算30分钟前的时间用于判断进程是否为空final long oldTime now - ProcessList.MAX_EMPTY_TIME;// 获取LRU列表中的进程数量final int N mLruProcesses.size();// 增加OOM调整值的序列号用于标识调整周期mAdjSeq;// 初始化服务进程的数量mNewNumServiceProcs 0;mNewNumAServiceProcs 0;// 根据系统配置计算空进程和缓存进程的最大数量final int emptyProcessLimit;final int cachedProcessLimit;if (mProcessLimit 0) {emptyProcessLimit cachedProcessLimit 0;} else if (mProcessLimit 1) {emptyProcessLimit 1;cachedProcessLimit 0;} else {emptyProcessLimit ProcessList.computeEmptyProcessLimit(mProcessLimit);cachedProcessLimit mProcessLimit - emptyProcessLimit;}// 计算缓存进程的调整值步长int numSlots (ProcessList.CACHED_APP_MAX_ADJ- ProcessList.CACHED_APP_MIN_ADJ 1) / 2;// 计算空进程的数量int numEmptyProcs N - mNumNonCachedProcs - mNumCachedHiddenProcs;if (numEmptyProcs cachedProcessLimit) {numEmptyProcs cachedProcessLimit;}// 计算空进程和缓存进程的调整值步长因子int emptyFactor numEmptyProcs / numSlots;if (emptyFactor 1) emptyFactor 1;int cachedFactor (mNumCachedHiddenProcs 0 ? mNumCachedHiddenProcs : 1) / numSlots;if (cachedFactor 1) cachedFactor 1;// 初始化步长计数器int stepCached 0;int stepEmpty 0;// 初始化缓存和空进程的数量计数器int numCached 0;int numEmpty 0;int numTrimming 0;// 初始化非缓存进程和缓存隐藏进程的数量计数器mNumNonCachedProcs 0;mNumCachedHiddenProcs 0;// 初始化缓存和空进程的OOM调整值int curCachedAdj ProcessList.CACHED_APP_MIN_ADJ;int nextCachedAdj curCachedAdj 1;int curEmptyAdj ProcessList.CACHED_APP_MIN_ADJ;int nextEmptyAdj curEmptyAdj 2;// 遍历LRU列表更新每个进程的OOM调整值for (int i N - 1; i 0; i--) {ProcessRecord app mLruProcesses.get(i);// 如果进程没有被杀死并且有线程更新其OOM调整值if (!app.killedByAm app.thread ! null) {app.procStateChanged false;// 计算进程的OOM调整值computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);if (app.curAdj ProcessList.UNKNOWN_ADJ) {// 根据进程状态调整OOM值switch (app.curProcState) {case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:app.curRawAdj curCachedAdj;app.curAdj app.modifyRawOomAdj(curCachedAdj);if (curCachedAdj ! nextCachedAdj) {stepCached;if (stepCached cachedFactor) {stepCached 0;curCachedAdj nextCachedAdj;nextCachedAdj 2;if (nextCachedAdj ProcessList.CACHED_APP_MAX_ADJ) {nextCachedAdj ProcessList.CACHED_APP_MAX_ADJ;}}}break;default:app.curRawAdj curEmptyAdj;app.curAdj app.modifyRawOomAdj(curEmptyAdj);if (curEmptyAdj ! nextEmptyAdj) {stepEmpty;if (stepEmpty emptyFactor) {stepEmpty 0;curEmptyAdj nextEmptyAdj;nextEmptyAdj 2;if (nextEmptyAdj ProcessList.CACHED_APP_MAX_ADJ) {nextEmptyAdj ProcessList.CACHED_APP_MAX_ADJ;}}}break;}}// 应用OOM调整值applyOomAdjLocked(app, TOP_APP, true, now);// 根据进程类型计数switch (app.curProcState) {case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:mNumCachedHiddenProcs;numCached;if (numCached cachedProcessLimit) {app.kill(cached # numCached, true);}break;case ActivityManager.PROCESS_STATE_CACHED_EMPTY:if (numEmpty ProcessList.TRIM_EMPTY_APPS app.lastActivityTime oldTime) {app.kill(empty for ((oldTime ProcessList.MAX_EMPTY_TIME - app.lastActivityTime) / 1000) s, true);} else {numEmpty;if (numEmpty emptyProcessLimit) {app.kill(empty # numEmpty, true);}}break;default:mNumNonCachedProcs;break;}// 杀死孤立的进程if (app.isolated app.services.size() 0) {app.kill(isolated not needed, true);}// 计算需要调整的进程数量if (app.curProcState ActivityManager.PROCESS_STATE_HOME !app.killedByAm) {numTrimming;}}}//...} updateOomAdjLocked方法的前半部分主要负责初始化OOM调整值的计算环境包括确定进程的OOM调整值序列、计算空进程和缓存进程的限制数量、以及遍历LRU列表更新每个进程的OOM调整值。这一部分还涉及到根据进程的活动状态如前台活动、服务状态等来调整其在LRU列表中的位置并决定是否需要杀死超出内存限制的进程。 同时我们这里关注两个关键方法computeOomAdjLocked和applyOomAdjLocked 1 computeOomAdjLocked方法 computeOomAdjLocked方法用于计算进程的OOM调整值在android的各个版本中该方法差异较大但核心功能和设计目的不变核心功能和设计目的解读如下 动态调整OOM值computeOomAdjLocked方法根据进程的活动状态如前台活动、服务状态等来计算其OOM值。这个值决定了进程在系统内存不足时被回收的可能性值越高表示进程越不可能被杀死。进程优先级管理方法通过评估进程的重要性来调整其优先级确保在内存紧张时前台进程和关键后台进程能够获得更多的保护而后台或不活跃的进程则更容易被牺牲以释放内存。响应系统状态变化当Android四大组件Activity、Service、Broadcast Receiver、Content Provider的状态发生变化时该方法会被调用来更新相应进程的OOM值以反映这些变化对进程优先级的影响。优化内存使用设计目的是在保证用户体验的同时合理利用系统资源。通过对进程OOM值的动态管理系统能够在内存紧张时优先保留用户最可能需要的进程同时释放那些对用户体验影响较小的进程所占用的内存。系统稳定性和响应性通过合理分配内存资源computeOomAdjLocked方法有助于提高系统的稳定性和响应性。它确保了在内存不足的情况下系统能够做出合理的决策避免因内存不足导致的系统崩溃或应用异常。 computeOomAdjLocked方法是Android系统中一个重要的内存管理机制它通过动态调整进程的OOM值来优化内存使用保护关键进程并在内存紧张时做出合理的内存回收决策。 2 applyOomAdjLocked方法 applyOomAdjLocked方法主要根据进程的状态和重要性动态调整其OOM值以优化系统内存管理。applyOomAdjLocked方法的核心功能和设计目的 其核心功能是将之前通过computeOomAdjLocked方法计算得出的OOM值应用到各个进程上以此来调整进程的内存优先级。设计目的在于确保在系统内存紧张时能够根据进程的重要性和当前状态合理地决定哪些进程应该被优先保留哪些可以被牺牲以释放内存资源。 通过这种方式系统能够在保证用户体验的同时有效管理内存资源避免因内存不足导致的系统不稳定或崩溃。 3.2.2 updateOomAdjLocked后半段代码解读 updateOomAdjLocked后半段代码实现如下所示 final void updateOomAdjLocked() {//...// 更新服务进程数量mNumServiceProcs mNewNumServiceProcs;// 计算缓存和空进程的总数final int numCachedAndEmpty numCached numEmpty;// 根据缓存和空进程的数量确定内存因子用于调整进程的内存使用int memFactor;if (numCached ProcessList.TRIM_CACHED_APPS numEmpty ProcessList.TRIM_EMPTY_APPS) {if (numCachedAndEmpty ProcessList.TRIM_CRITICAL_THRESHOLD) {memFactor ProcessStats.ADJ_MEM_FACTOR_CRITICAL;} else if (numCachedAndEmpty ProcessList.TRIM_LOW_THRESHOLD) {memFactor ProcessStats.ADJ_MEM_FACTOR_LOW;} else {memFactor ProcessStats.ADJ_MEM_FACTOR_MODERATE;}} else {memFactor ProcessStats.ADJ_MEM_FACTOR_NORMAL;}// 如果新的内存因子大于上次的内存因子且不允许降低内存级别或进程数量没有变化则保持上次的内存因子if (memFactor mLastMemoryLevel) {if (!mAllowLowerMemLevel || mLruProcesses.size() mLastNumProcesses) {memFactor mLastMemoryLevel;}}// 更新上次的内存因子和进程数量mLastMemoryLevel memFactor;mLastNumProcesses mLruProcesses.size();// 根据内存因子更新进程的状态boolean allChanged mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);final int trackerMemFactor mProcessStats.getMemFactorLocked();// 如果内存因子不是正常级别则根据内存状况对进程进行内存修剪if (memFactor ! ProcessStats.ADJ_MEM_FACTOR_NORMAL) {// 记录低内存开始时间if (mLowRamStartTime 0) {mLowRamStartTime now;}// 根据内存因子确定修剪级别int fgTrimLevel;switch (memFactor) {case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:fgTrimLevel ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;break;case ProcessStats.ADJ_MEM_FACTOR_LOW:fgTrimLevel ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;break;default:fgTrimLevel ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;break;}// 计算修剪步长int factor numTrimming / 3;int minFactor 2;if (mHomeProcess ! null) minFactor;if (mPreviousProcess ! null) minFactor;if (factor minFactor) factor minFactor;// 遍历所有进程根据修剪级别进行内存修剪int curLevel ComponentCallbacks2.TRIM_MEMORY_COMPLETE;for (int i N - 1; i 0; i--) {ProcessRecord app mLruProcesses.get(i);if (allChanged || app.procStateChanged) {setProcessTrackerStateLocked(app, trackerMemFactor, now);app.procStateChanged false;}// 对于HOME和PREVIOUS进程以及需要修剪的进程进行内存修剪if (app.curProcState ActivityManager.PROCESS_STATE_HOME !app.killedByAm) {if (app.trimMemoryLevel curLevel app.thread ! null) {try {app.thread.scheduleTrimMemory(curLevel);} catch (RemoteException e) {}}app.trimMemoryLevel curLevel;// 更新修剪级别step;if (step factor) {step 0;switch (curLevel) {case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:curLevel ComponentCallbacks2.TRIM_MEMORY_MODERATE;break;case ComponentCallbacks2.TRIM_MEMORY_MODERATE:curLevel ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;break;}}} else if (app.curProcState ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {// 对于重量级进程进行背景内存修剪if (app.trimMemoryLevel ComponentCallbacks2.TRIM_MEMORY_BACKGROUND app.thread ! null) {try {app.thread.scheduleTrimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);} catch (RemoteException e) {}}app.trimMemoryLevel ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;} else {// 对于其他进程根据需要进行内存修剪if ((app.curProcState ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND|| app.systemNoUi) app.pendingUiClean) {final int level ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;if (app.trimMemoryLevel level app.thread ! null) {try {app.thread.scheduleTrimMemory(level);} catch (RemoteException e) {}}app.pendingUiClean false;}if (app.trimMemoryLevel fgTrimLevel app.thread ! null) {try {app.thread.scheduleTrimMemory(fgTrimLevel);} catch (RemoteException e) {}}app.trimMemoryLevel fgTrimLevel;}}} else {// 如果内存因子是正常级别则重置低内存开始时间if (mLowRamStartTime ! 0) {mLowRamTimeSinceLastIdle now - mLowRamStartTime;mLowRamStartTime 0;}for (int i N - 1; i 0; i--) {ProcessRecord app mLruProcesses.get(i);if (allChanged || app.procStateChanged) {setProcessTrackerStateLocked(app, trackerMemFactor, now);app.procStateChanged false;}// 对于需要清理UI的进程进行UI隐藏内存修剪if ((app.curProcState ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND|| app.systemNoUi) app.pendingUiClean) {if (app.trimMemoryLevel ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN app.thread ! null) {try {app.thread.scheduleTrimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);} catch (RemoteException e) {}}app.pendingUiClean false;}app.trimMemoryLevel 0;}}// 如果设置了总是结束活动的选项则安排销毁所有活动if (mAlwaysFinishActivities) {mStackSupervisor.scheduleDestroyAllActivities(null, always-finish);}// 如果所有进程的状态都发生了变化则请求所有进程的PSSProportional Set Size数据if (allChanged) {requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());}// 如果进程统计数据应该被写入则异步写入if (mProcessStats.shouldWriteNowLocked(now)) {mHandler.post(new Runnable() {Override public void run() {synchronized (ActivityManagerService.this) {mProcessStats.writeStateAsyncLocked();}}});}} 后半部分则专注于根据当前的内存使用情况来调整进程的内存使用级别即内存因子memFactor。它通过计算得出当前的内存因子并根据该因子对进程进行内存修剪以释放内存资源。这一部分还涉及到更新进程的内存修剪级别并在必要时触发进程的内存修剪操作以响应系统的内存压力。 在updateOomAdjLocked方法中根据前半段和后半段的代码针对oom_adj关键变量的调整主要集中在以下几个方面解读如下 OOM调整值curAdj每个ProcessRecord对象中的curAdj字段被调整这个字段代表了进程的当前OOM调整值它直接影响到进程在内存不足时被杀死的优先级。进程状态curProcStateProcessRecord中的curProcState字段被更新反映了进程的当前状态如前台、后台、服务等这有助于确定进程的OOM调整值。内存因子memFactormemFactor变量根据系统的内存状况和进程的数量被计算出来用于决定整体的内存调整策略。服务进程计数mNewNumServiceProcs 和 mNumServiceProcsmNewNumServiceProcs用于临时计数服务进程的数量而mNumServiceProcs是最终的服务进程数量这些计数用于内存调整决策。非缓存进程和缓存隐藏进程计数mNumNonCachedProcs 和 mNumCachedHiddenProcs这些变量用于计数非缓存进程和缓存隐藏进程的数量它们在计算OOM调整值时起到重要作用。进程跟踪器状态setProcessTrackerStateLocked该方法被调用来更新进程的内存修剪级别这影响了进程如何响应系统的内存压力。内存修剪级别trimMemoryLeveltrimMemoryLevel字段在ProcessRecord中被设置指示进程应该采取的内存修剪行动。低内存开始时间mLowRamStartTime记录系统进入低内存状态的时间用于跟踪和管理低内存期间的内存调整策略。 这些关键变量的调整确保了Android系统能够根据当前的内存状况和进程的活动状态动态地管理内存资源优化用户体验并在内存不足时做出合理的进程杀死决策。通过这种方式系统能够在保证前台和关键进程的稳定性的同时合理回收后台进程的内存资源。 updateOomAdjLocked方法整体上是Android系统中一个关键的内存管理机制它确保了在内存资源有限的情况下系统能够根据进程的重要性和活动状态动态调整其OOM调整值和内存使用级别。通过这种方法系统能够在内存不足时优先保护前台和关键进程同时合理地回收后台进程的内存资源从而优化整体的系统性能和用户体验。这个方法体现了Android系统在面对不同内存压力时的响应策略包括进程的OOM调整、内存修剪和进程状态的更新这些都是为了在保证系统稳定性的同时尽可能地提高内存使用效率。
http://www.hkea.cn/news/14384753/

相关文章:

  • 查看网站 vps简单的编程代码
  • 哈尔滨网站设计人网站建设公司福州
  • 5G网站建设公司做网站域名归谁
  • 售后软件网站开发宁波网站建设网络推广
  • 技术支持-鼎维重庆网站建设专家国家认可提升学历正规机构
  • 网站主页和子页怎么做网页设计与制作实训总结2000字
  • 网站源码 酷成品网站好吗
  • 如何修改网站后台搜索引擎营销案例
  • 湛江专业网站建设公司海南信息港官网
  • 温州网站建设推广建设云南省癌症中心网站
  • 百度做网站的dede可以做视频网站
  • 上海天华建筑设计有限公司地址南宁排名seo公司
  • 多用户商城app网站值不值得做seo
  • 电商美工招聘信息seo优化方案策划书
  • 购物网站建设好处南昌哪个公司做网站好
  • 单位网站怎么做wordpress注册登录右边
  • 番禺响应式网站建设wordpress标题去掉私密
  • 网站要备案吗网站关键词的选择
  • 找网络公司做网站需要注意的制作ppt的软件电脑版
  • 怎么做外网网站监控软件百度手机应用商店
  • 网站怎么做图片超链接dw大学生网站制作作业免费下载
  • 专业的o2o网站建设深圳建设厅网站官网
  • 建设网站聊天室安阳网站建设官网
  • 网站仿制教程建设厅安检局网站
  • 通了网站建设wordpress密码忘记了怎么办
  • 来宾住房和城乡建设网站掀浪云网站建设
  • 如何做网站页面自己搭建聊天软件
  • 网站备案的意思网站主办者有效证件电子件
  • 网站建设ppt方案模板下载丽江市企业网站
  • 没后台的网站怎么做优化做网赌网站需要多少钱