Android Framework 常见解决方案(25-2)定制CPUSET解决方案-system修改及编译部分调整

1 原理说明

这个方案有如下基本需求:

  • 构建自定义CPUSET,/dev/cpuset中包含一个全新的cpuset分组。且可以通过set_cpuset_policy和set_sched_policy接口可以设置自定义CPUSET。
  • 开机启动后可以通过zygote判定来对特定的应用进程设置CPUSET,并一直保持,且保证自定义CPUSET不受其他CPUSET影响,持续独立。

原理上因为修改代码涉及部分较多,因此共分3个部分:

  1. framework修改:添加SCHED GROUP和THREAD GROUP(THREAD_GROUP_对应SP_)的支持,且支持开机启动后直接设置。applyOomAdjLSP的判定保持不变。
  2. system修改:添加SP_CUSTOM的支持及set_cpuset_policy和set_sched_policy接口等支持,同时修改task_profiles.json,添加SP_CUSTOM CPUSET的支持。
  3. init.rc修改及编译部分调整:对自定义cpuset节点进行操作,vndk部分编译需要重新调整方案以及不修改VNDK如何保证编译通过。

由于修改中涉及代码量过大,这里拆分成两节进行展示。本章节主要针对第2部分和第3部分修改进行说明。上一篇文章👇

Android Framework 常见解决方案(25-1)定制CPUSET解决方案-framework部分修改

主要对第1部分修改进行说明。

2 修改方案(Android S)

2.1 system部分修改

针对system分区修改。具体修改方案如下(这里以S版本修改为主,Q和R有一些差异但原理不变)

在$AOSP/system/core/libprocessgroup/include/processgroup/sched_policy.h文件中修改:

/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
typedef enum {SP_DEFAULT = -1,SP_BACKGROUND = 0,SP_FOREGROUND = 1,SP_SYSTEM = 2,SP_AUDIO_APP = 3,SP_AUDIO_SYS = 4,SP_TOP_APP = 5,SP_RT_APP = 6,SP_RESTRICTED = 7,
+    SP_CUSTOM = 8,SP_CNT,SP_MAX = SP_CNT - 1,SP_SYSTEM_DEFAULT = SP_FOREGROUND,
} SchedPolicy;

这里注意,按照顺序填写修改相对简单,因为后续会用到SP_CNT和SP_MAX这两个变量,代码中还会有许多的遍历操作,因此最好采用累加方案,不要设置其他值。

本方案的修改比较全面,即支持set_cpuset_policy,也兼容到set_sched_policy,在实际操作中,可根据需要只修改其中一个即可。

在$AOSP/system/core/libprocessgroup/sched_policy.cpp文件中修改:

//修改set_cpuset_policy,添加SP_CUSTOM的处理
int set_cpuset_policy(int tid, SchedPolicy policy) {if (tid == 0) {tid = GetThreadId();}policy = _policy(policy);switch (policy) {case SP_BACKGROUND:return SetTaskProfiles(tid, {"CPUSET_SP_BACKGROUND", "BlkIOBackground"}, true) ? 0 : -1;case SP_FOREGROUND:return SetTaskProfiles(tid, {"CPUSET_SP_FOREGROUND", "BlkIOForeground"}, true) ? 0 : -1;case SP_AUDIO_APP:case SP_AUDIO_SYS:return SetTaskProfiles(tid, {"CPUSET_SP_FOREGROUND", "AudioAppCapacity", "BlkIOForeground"}, true) ? 0 : -1;case SP_TOP_APP:return SetTaskProfiles(tid, {"CPUSET_SP_TOP_APP", "BlkIOBackground"}, true) ? 0 : -1;case SP_SYSTEM:return SetTaskProfiles(tid, {"CPUSET_SP_SYSTEM", "BlkIOForeground"}, true) ? 0 : -1;case SP_RESTRICTED:return SetTaskProfiles(tid, {"CPUSET_SP_RESTRICTED"}, true) ? 0 : -1;
+        case SP_CUSTOM:
+            return SetTaskProfiles(tid, {"CPUSET_SP_CUSTOM"}, true) ? 0 : -1;default:break;}return 0;
}//修改set_sched_policy,添加SP_CUSTOM的处理
int set_sched_policy(int tid, SchedPolicy policy) {
//...
#if POLICY_DEBUG //注意:这一段的修改主要是调试使用,功能实现上可以不添加该部分
//...switch (policy) {case SP_BACKGROUND:SLOGD("vvv tid %d (%s)", tid, thread_name);break;case SP_FOREGROUND:case SP_AUDIO_APP:case SP_AUDIO_SYS:case SP_TOP_APP:SLOGD("^^^ tid %d policy %d (%s)", tid, policy, thread_name);break;case SP_SYSTEM:SLOGD("/// tid %d (%s)", tid, thread_name);break;case SP_RT_APP:SLOGD("RT  tid %d (%s)", tid, thread_name);break;
+        case SP_CUSTOM:
+            SLOGD("CUSTOM|xxx tid %d (%s)", tid, thread_name);
+            break;default:SLOGD("??? tid %d (%s)", tid, thread_name);break;}
#endif
//...switch (policy) {case SP_BACKGROUND:return SetTaskProfiles(tid, {"SCHED_SP_BACKGROUND", "BlkIOBackground"}, true) ? 0 : -1;case SP_FOREGROUND:case SP_AUDIO_APP:case SP_AUDIO_SYS:return SetTaskProfiles(tid, {"SCHED_SP_FOREGROUND", "BlkIOForeground"}, true) ? 0 : -1;case SP_TOP_APP:return SetTaskProfiles(tid, {"SCHED_SP_TOP_APP", "BlkIOForeground"}, true) ? 0 : -1;case SP_SYSTEM:return SetTaskProfiles(tid, {"SCHED_SP_SYSTEM"}, true) ? 0 : -1;case SP_RT_APP:return SetTaskProfiles(tid, {"SCHED_SP_RT_APP", "BlkIOForeground"}, true) ? 0 : -1;case SP_CUSTOM:return SetTaskProfiles(tid, {"SCHED_SP_CUSTOM"}, true) ? 0 : -1;default:return SetTaskProfiles(tid, {"SCHED_SP_DEFAULT"}, true) ? 0 : -1;}return 0;}
//修改get_sched_policy_from_group,添加SP_CUSTOM的处理
static int get_sched_policy_from_group(const std::string& group, SchedPolicy* policy) {if (group.empty()) {*policy = SP_FOREGROUND;} else if (group == "foreground") {*policy = SP_FOREGROUND;} else if (group == "system-background") {*policy = SP_SYSTEM;} else if (group == "background") {*policy = SP_BACKGROUND;} else if (group == "top-app") {*policy = SP_TOP_APP;} else if (group == "restricted") {*policy = SP_RESTRICTED;} else if (group == "audio-app") {*policy = SP_AUDIO_APP;} else if (group == "custom") {*policy = SP_CUSTOM;} else {errno = ERANGE;return -1;}return 0;
}//修改get_sched_policy_name,添加SP_CUSTOM的处理
const char* get_sched_policy_name(SchedPolicy policy) {policy = _policy(policy);static const char* const kSchedPolicyNames[] = {[SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = "  ",[SP_AUDIO_APP] = "aa",  [SP_AUDIO_SYS] = "as",  [SP_TOP_APP] = "ta",[SP_RT_APP] = "rt",     [SP_RESTRICTED] = "rs",[SP_CUSTOM] = "ct",};static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");if (policy < SP_BACKGROUND || policy >= SP_CNT) {return nullptr;}return kSchedPolicyNames[policy];
}//修改get_cpuset_policy_profile_name,添加SP_CUSTOM的处理
const char* get_cpuset_policy_profile_name(SchedPolicy policy) {/**  cpuset profile array for:*  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),*  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
-     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7), SP_CUSTOM(8)*  index is policy + 1*  this need keep in sync with SchedPolicy enum*/static constexpr const char* kCpusetProfiles[SP_CNT + 1] = {"CPUSET_SP_DEFAULT", "CPUSET_SP_BACKGROUND", "CPUSET_SP_FOREGROUND","CPUSET_SP_SYSTEM",  "CPUSET_SP_FOREGROUND", "CPUSET_SP_FOREGROUND",
-            "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT",    "CPUSET_SP_RESTRICTED"
+            "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT",    "CPUSET_SP_RESTRICTED","CPUSET_SP_CUSTOM"};if (policy < SP_DEFAULT || policy >= SP_CNT) {return nullptr;}return kCpusetProfiles[policy + 1];
}//修改get_sched_policy_profile_name,添加SP_CUSTOM的处理
const char* get_sched_policy_profile_name(SchedPolicy policy) {/**  sched profile array for:*  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),*  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
-     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7),SP_CUSTOM(8)*  index is policy + 1*  this need keep in sync with SchedPolicy enum*/static constexpr const char* kSchedProfiles[SP_CNT + 1] = {"SCHED_SP_DEFAULT", "SCHED_SP_BACKGROUND", "SCHED_SP_FOREGROUND","SCHED_SP_SYSTEM",  "SCHED_SP_FOREGROUND", "SCHED_SP_FOREGROUND",
-            "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP",     "SCHED_SP_DEFAULT"
+            "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP",     "SCHED_SP_DEFAULT","SCHED_SP_CUSTOM"};if (policy < SP_DEFAULT || policy >= SP_CNT) {return nullptr;}return kSchedProfiles[policy + 1];
}

以上2部分主要是逻辑的修改,接下来是配置文件的修改,在$AOSP/system/core/libprocessgroup/profiles/task_profiles.json文件中修改:

{"Attributes": [{"Name": "LowCapacityCPUs","Controller": "cpuset","File": "background/cpus"},...
+    {
+      "Name": "CustomCPUs",
+      "Controller": "cpuset",
+      "File": "custom/cpus"
+    },...{"Name": "FreezerState","Controller": "freezer","File": "cgroup.freeze"}],"Profiles": [{"Name": "HighEnergySaving","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "cpu","Path": "background"}}]},...
+    {
+      "Name": "CustomPerformance",
+      "Actions" : [
+        {
+          "Name" : "JoinCgroup",
+          "Params" :
+          {
+            "Controller": "cpuset",
+            "Path": "custom"
+          }
+        }
+      ]
+    },...{"Name": "SystemMemoryProcess","Actions": [{"Name": "JoinCgroup","Params":{"Controller": "memory","Path": "system"}}]}],"AggregateProfiles": [{"Name": "SCHED_SP_DEFAULT","Profiles": [ "TimerSlackNormal" ]},...{"Name": "SCHED_SP_RT_APP","Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]},
+    {
+      "Name": "SCHED_SP_CUSTOM",
+      "Profiles": [ "CUSTOMPerformance" ]
+    },...
+    {
+      "Name": "CPUSET_SP_CUSTOM",
+      "Profiles": [ "CUSTOMPerformance" ]
+    },...{"Name": "Dex2OatBootComplete","Profiles": [ "Dex2oatPerformance", "LowIoPriority", "TimerSlackHigh" ]}]
}

至此,system相关修改就结束了。主要是SP_CUSTOM相关逻辑的添加,配置文件task_profiles.json的修改,接口set_cpuset_policy和set_sched_policy的支持等。

2.2 init.rc及编译部分调整

 为添加cpuset相关节点,需要修改init.rc文件,这里根据android源码的需要调整到对应的rc中添加即可。具体init.rc修改内容如下:

#第一部分:on init中添加:
...
+#custom add start
+    mkdir /dev/stune/custom
+    chown system system /dev/stune/custom
+    chown system system /dev/stune/custom/tasks
+    chmod 0664 /dev/stune/custom/tasks
+    mkdir /dev/cpuset/custom
+    copy /dev/cpuset/cpus /dev/cpuset/custom/cpus
+    copy /dev/cpuset/mems /dev/cpuset/custom/mems
+    chown system system /dev/cpuset/custom
+    chown system system /dev/cpuset/custom/tasks
+    chown system system /dev/cpuset/custom/cgroup.procs
+    chmod 0664 /dev/cpuset/custom/tasks
+    chmod 0664 /dev/cpuset/custom/cgroup.procs
+#custom add end
...
#第二部分:系统启动完成后添加:
+#custom add start
+on property:sys.boot_completed=1
+   write /dev/cpuset/custom/cpus 6-7
+   write /dev/cpuset/custom/mems 0
+#custom add end

这里主要是通过init.rc文件添加cpuset相关节点,以及修改cpuset相关节点的权限和owner,以及写入值操作。这样,在开机启动后就可以在/dev/cpuset/目录下看到自定义cpuset对应的custom节点。

至此代码和配置文件都已经修改完了。

接下来就需要编译了,但是编译这里要避免vndk报错的问题,需要有先执行如下脚本内容:

source build/envsetup.sh && lunch xxx
cd ./development/vndk/tools/header-checker/utils/
#这里的xxx一般是指out/target/product之后的路径
./create_reference_dumps.py -l libprocessgroup -product xxx

重新编译vndk,否则会出现如下类似的编译错误,如下所示:

error: VNDK library: XXX
******************************************************
error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py  -l libprocessgroup
ninja failed with: exit status 1
#### failed to build some targets ####

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/608764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring MVC学习之——了解MVC设计模式

MVC设计模式 MVC介绍 MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&#xff0c;在数据变化时更新…

HTML5中form表单防止重复提交的两种方法

form表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题 (1)点击提交按钮两次。 (2)点击刷新按钮。 (3)使用浏览器后退按钮重复之前的操作 导致重复提交表单。 (4)浏览器重复的HTTP请求。 (5)用户提交表单时可能因为网…

Java项目:112SSM在线电影订票系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 在线电影订票系统基于SpringSpringMVCMybatis开发&#xff0c;系统分为前台和后台&#xff0c;前台主要用来用户浏览电影信息&#xff0c;订票&#xff0c…

Java synchronized 和 volatile 的区别是什么?

Java synchronized 和 volatile 的区别是什么&#xff1f; Java 中的 synchronized 和 volatile 都涉及到多线程编程&#xff0c;但它们的作用和使用场景略有不同。 synchronized 关键字&#xff1a; 作用&#xff1a; 用于实现对共享资源的互斥访问&#xff0c;确保在同一时…

人工智能任务2-读懂Transformer模型的十个灵魂拷问问题,深度理解Transformer模型架构

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能任务2-读懂Transformer模型的十个灵魂拷问问题&#xff0c;深度理解Transformer模型架构。Transformer模型是一种基于自注意力机制的神经网络架构&#xff0c;被广泛用于自然语言处理任务中&#xff0c;如机…

系分笔记数据库技术之数据库安全措施

文章目录 1、概要2、数据库的保护措施3、数据库的故障4、备份和日志5、总结 1、概要 数据库设计是考试重点&#xff0c;常考和必考内容&#xff0c;本篇主要记录了知识点&#xff1a;数据库故障及解决、数据库安全保护措施和数据库备份及恢复。 2、数据库的保护措施 数据库安全…

es6 定义变量 let 跟cosnt 区别

es6 定义变量 let 跟cosnt 区别 以上内容由chatgpt中文网 动态生成 可变性&#xff1a; let&#xff1a; 声明的变量具有可变性&#xff0c;可以被重新赋值。 const&#xff1a; 声明的变量是常量&#xff0c;一旦赋值后就不能再重新赋值。但需要注意的是&#xff0c;对于对象…

C++系列十六:枚举

枚举 一、C枚举基础 在C中&#xff0c;枚举&#xff08;Enumeration&#xff09;是一种用户定义的数据类型&#xff0c;它包含一组整数值&#xff0c;每个值都与一个标识符关联。通过使用枚举&#xff0c;我们可以使代码更加清晰易懂&#xff0c;避免使用魔术数字或字符串。 …

卡码网Java基础课 | 1. A+B问题I

卡码网Java基础课|1. AB问题I 类和面向对象new关键字程序基本结构方法的组成返回类型ReturnType函数名methodType形参列表方法体 输入输出Scanner类的使用 变量完整代码输入&#xff1a;Scanner类的使用private和public 类和面向对象 一个类具有一些“属性”和“方法”&#x…

云卷云舒:【实战篇】云主机/虚拟机迁移

1. 简介 用户原有业务通过不同版本型号、不同操作系统的主机承载&#xff0c;形式上包括物理服务器、虚拟机、公有云主机等。随着业务不断扩张&#xff0c;需要将其业务云化转型&#xff0c;必须保证上云过程数据完整&#xff0c;业务平滑过度。 如果将所有业务系统都重新部署…

以太坊开发者会议回顾:坎昆升级、硬分叉与布拉格

作者&#xff1a;Christine Kim Galaxy研究副总裁 编译&#xff1a;秦晋 碳链价值 2024年1月4日&#xff0c;以太坊开发人员齐聚Zoom for All Core Developers Execution (ACDE) Call #178 上。ACDE电话会议通常由以太坊基金会协议负责人Tim Beiko主持&#xff0c;是一个开发人…

Orchestrator源码解读2-故障失败发现

目录 目录 前言 核心流程函数调用路径 GetReplicationAnalysis 故障类型和对应的处理函数 拓扑结构警告类型 与MHA相比 前言 Orchestrator另外一个重要的功能是监控集群&#xff0c;发现故障。根据从复制拓扑本身获得的信息&#xff0c;它可以识别各种故障场景。Orchest…

Apollo基础 - Frenet坐标系

Frenet与笛卡尔坐标系的转换详细推导见&#xff1a;b站老王 自动驾驶决策规划学习记录&#xff08;四&#xff09; Apollo相关代码&#xff1a; modules/common/math/cartesian_frenet_conversion.h #pragma once #include <array> #include "modules/common/mat…

怎么一边讲PPT一边录视频 如何一边录制PPT一边录制人像 录屏软件免费录屏 PPT录制怎么录制

随着新媒体技术的发展&#xff0c;短视频和直播越来越火。越来越多的小伙伴加入了视频制作的大军&#xff0c;那么你想知道怎么一边讲PPT一边录视频&#xff0c;如何一边录制PPT一边录制人像吗&#xff1f; 一、怎么一边讲PPT一边录视频 我们可以借助PPT本身自带的屏幕录制功能…

Linux的发展历程:从诞生到全球应用

一、前言 Linux作为一个开源操作系统&#xff0c;经历了令人瞩目的发展历程。从最初的创意到如今在全球范围内得到广泛应用&#xff0c;Linux不仅是技术的杰出代表&#xff0c;更是开源精神的典范。本文将追溯Linux的发展历程&#xff0c;深入了解它是如何从一个个人项目演变为…

【docker笔记】Docker容器数据卷

Docker容器数据卷 卷就是目录或者文件&#xff0c;存在于一个或多个容器中&#xff0c;由docker挂载到容器&#xff0c;但不属于联合文件系统&#xff0c;因此能够绕过Union File System提供一些用于持续存储或共享数据的特性 卷的设计目的就是数据的持久化&#xff0c;完全独…

kotlin map{}和mapOf{}

map{}的作用 map 让集合中的每个元素应用给定的转换函数&#xff08;transform&#xff09;&#xff0c;然后生成并返回一个新的 List<R> val numbers listOf(1, 2, 3, 4, 5) //map 让集合中的每个元素应用给定的转换函数&#xff08;transform&#xff09;&#xff0…

VMware Workstation安装以及配置模板机

文章目录 一、VMware Workstation软件下载安装1、下载2、安装 二、CentOS7模板机安装1、创建虚拟机2、安装系统 三、网络配置 一、VMware Workstation软件下载安装 1、下载 下载地址&#xff1a;https://download3.vmware.com/software/wkst/file/VMware-workstation-full-15…

css中的变量和辅助函数

变量 --name 两个破折号加变量名称&#xff08;可以在当前的选择器内定义&#xff09;var(--*) 命名规则 body {--深蓝: #369;background-color: var(--深蓝); } 变量值只能做用属性值&#xff0c;不能用做属性名。变量命名不能包含 $,[,^,(,% 等字符 普通字符局限在只要是数…

软件测试|MySQL逻辑运算符使用详解

简介 在MySQL中&#xff0c;逻辑运算符用于处理布尔类型的数据&#xff0c;进行逻辑判断和组合条件。逻辑运算符主要包括AND、OR、NOT三种&#xff0c;它们可以帮助我们在查询和条件语句中进行复杂的逻辑操作。本文将详细介绍MySQL中逻辑运算符的使用方法和示例。 AND运算符 …