Android Framework AMS(01)AMS启动及相关初始化1-4

该系列文章总纲链接:专题总纲目录 Android Framework 总纲


本章关键点总结 & 说明:

说明:本章节主要涉及systemserver启动AMS及初始化AMS相关操作。同时由于该部分内容分析过多,因此拆成2个章节,本章节是第一章节,第二章节文章链接为:

Android Framework AMS(02)AMS启动及相关初始化5-8

systemserver在启动AMS(ActivityManagerService)时,不仅仅是做简单的AMS服务启动,还有很多的其他初始化相关操作,这里我们以SystemServer启动流程为主线,对AMS启动及相关逻辑进行初始化操作进行分析,接下来我们通过代码来看看具体的操作逻辑。相关代码如下:

// SystemServer//...// 定义系统服务的成员变量private ActivityManagerService mActivityManagerService;private SystemServiceManager mSystemServiceManager;private PowerManagerService mPowerManagerService;private PackageManagerService mPackageManagerService;//...private void startBootstrapServices() {// 启动引导服务,这些服务在系统启动的早期阶段被启动// ...// 关键点1:启动ActivityManagerService服务mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();// 关键点2:为ActivityManagerService设置系统服务管理器mActivityManagerService.setSystemServiceManager(mSystemServiceManager);// 启动PowerManagerService服务mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);// 关键点3:初始化电源管理mActivityManagerService.initPowerManagement();// 关键点4:将当前进程设置为系统进程mActivityManagerService.setSystemProcess();// ...}//...private void startCoreServices() {// 启动核心服务// ...// 为ActivityManagerService设置UsageStatsManager服务mActivityManagerService.setUsageStatsManager(LocalServices.getService(UsageStatsManagerInternal.class));// ...}//...private void startOtherServices() {// 启动其他服务// ...WindowManagerService wm = null;// ...// 关键点5:安装系统提供的ContentProvidersmActivityManagerService.installSystemProviders();// 初始化看门狗监控watchdog.init(context, mActivityManagerService);// 创建WindowManagerService服务wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,mActivityManagerService);// 关键点6:为ActivityManagerService设置WindowManagermActivityManagerService.setWindowManager(wm);final boolean safeMode = wm.detectSafeMode();if (safeMode) {// 检测安全模式// 进入安全模式mActivityManagerService.enterSafeMode();// 禁用JIT编译VMRuntime.getRuntime().disableJitCompilation();} else {// 启用JIT编译VMRuntime.getRuntime().startJitCompilation();}if (safeMode) {// 如果处于安全模式,显示安全模式覆盖层mActivityManagerService.showSafeModeOverlay();}// ...// 通知PowerManagerService系统已准备好mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());// 关键点7:当ActivityManagerService准备好后执行的操作mActivityManagerService.systemReady(new Runnable() {@Overridepublic void run() {// 启动系统服务管理器的下一个启动阶段mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);try {//关键点8:开始监控本地崩溃mActivityManagerService.startObservingNativeCrashes();} catch (Throwable e) {// 报告错误reportWtf("observing native crashes", e);}// ...WebViewFactory.prepareWebViewInSystemServer();try {// 尝试启动系统用户界面startSystemUi(context);} catch (Throwable e) {reportWtf("starting System UI", e);}try {//尝试通知挂载服务系统已准备就绪if (mountServiceF != null) mountServiceF.systemReady();} catch (Throwable e) {reportWtf("making Mount Service ready", e);}//...//其他各种服务准备就绪//...}});// ...}

以上代码通过关键点的标注,共列出了8个重要的调用,并对这些调用进行了简单的描述。整理如下:

  • 关键点1:启动ActivityManagerService服务。
  • 关键点2:为ActivityManagerService设置系统服务管理器。
  • 关键点3:初始化电源管理。
  • 关键点4:将当前进程设置为系统进程。
  • 关键点5:安装系统提供的ContentProviders。
  • 关键点6:为ActivityManagerService设置WindowManager。
  • 关键点7:当ActivityManagerService准备好后执行的操作。
  • 关键点8:开始监控本地崩溃。

接下来针对这8个关键点进行详细的解读。本章节主要关注关键点1-4部分,下一篇关注关键点5-8部分。

1 启动ActivityManagerService服务

这里从代码

mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();

开始分析,这里涉及的ActivityManagerService.Lifecycle是ActivityManagerService的一个内部类,它实现了 SystemService 接口。它的代码实现如下:

//ActivityManagerServicepublic static final class Lifecycle extends SystemService {private final ActivityManagerService mService;public Lifecycle(Context context) {super(context);mService = new ActivityManagerService(context);}@Overridepublic void onStart() {mService.start();}public ActivityManagerService getService() {return mService;}}

接下来分析mSystemServiceManager.startService的代码实现,具体如下:

//SystemServiceManager//...//关键流程step1public SystemService startService(String className) {final Class<SystemService> serviceClass;//...serviceClass = (Class<SystemService>)Class.forName(className);//...return startService(serviceClass);}//关键流程step2public <T extends SystemService> T startService(Class<T> serviceClass) {final String name = serviceClass.getName();// 创建服务实例if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("..." + SystemService.class.getName());}final T service;Constructor<T> constructor = serviceClass.getConstructor(Context.class);// 使用构造函数创建服务实例,传入mContext作为参数service = constructor.newInstance(mContext);//...mServices.add(service); // 将服务实例添加到服务列表中//...service.onStart(); // 调用服务的onStart方法,服务在这里进行初始化工作//...return service; // 返回创建的服务实例}

这里首先会调用的Lifecycle的构造器,实际上就是创建了一个ActivityManagerService对象,然后是执行Lifecycle的onStart方法,实际上是调用ActivityManagerService的start方法,start方法内容如下:

//ActivityManagerServiceprivate void start() {// 移除所有进程组。在Unix中,进程组是一个或多个进程的集合,它们可以一起接收信号。// 这个调用确保在AMS启动时,系统中不会有遗留的进程组影响新的系统服务。Process.removeAllProcessGroups();// 启动处理CPU信息的线程。mProcessCpuThread是一个监控CPU使用情况的后台线程,// 用于收集和更新CPU使用相关的统计信息。mProcessCpuThread.start();// 发布电池状态服务。电池状态服务(BatteryStatsService)负责监控设备的电池使用情况,// 包括应用程序对电池的消耗等信息。mBatteryStatsService.publish(mContext);// 发布应用操作服务。应用操作服务(AppOpsService)负责管理应用的操作记录,// 比如访问位置、联系人等敏感信息的权限检查。mAppOpsService.publish(mContext);// 将AppOpsService添加到本地服务中,以便其他系统组件可以访问它。LocalServices.addService(ActivityManagerInternal.class, new LocalService());}

start方法在AMS启动时执行一系列初始化操作,包括移除进程组、启动CPU监控线程、发布电池状态服务和应用操作服务,以及添加本地服务。这些步骤确保了AMS及其依赖的服务能够正确初始化,并为其他系统组件提供必要的服务和信息。

注意:mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class)这里返回的是一个Lifecycle类型的对象,最后通过Lifecycle的getService拿到创建好的ActivityManagerService对象。

整个过程中主要是做了一些ActivityManagerService初始化相关工作(start方法),然后返回了一个ActivityManagerService对象赋值给成员变量mActivityManagerService。

2 为ActivityManagerService设置系统服务管理器

这里从代码

mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

开始分析,代码实现上很简单,如下所示:

//ActivityManagerServicepublic void setSystemServiceManager(SystemServiceManager mgr) {mSystemServiceManager = mgr;}

但我们要了解这样设计背后的意义:SystemServiceManager是负责启动和维护系统服务的关键组件。在ActivityManagerService中调用setSystemServiceManager(mSystemServiceManager)的目的主要是:

  • 通信和协调:ActivityManagerService(AMS)作为Android系统中的核心服务之一,负责管理应用程序的生命周期。它需要与其他系统服务如PowerManagerService、WindowManagerService等紧密协作。通过设置SystemServiceManager,AMS可以确保这些服务之间能够顺利通信和协调工作,这对于整个系统的稳定性和性能至关重要。
  • 管理生命周期:系统服务的生命周期管理是SystemServiceManager的重要职责之一。AMS通过SystemServiceManager来控制其他服务的启动、运行和停止,确保在系统启动和关闭过程中,所有服务都能够按照正确的顺序进行初始化和清理。
  • 提供服务上下文:SystemServiceManager持有系统级的上下文(Context),AMS需要这个上下文来执行其管理应用程序和进程的职责。系统级上下文提供了对系统资源和权限的访问,这对于AMS来说是必不可少的。

总之,设置一个系统服务管理器的引用,这样AMS就可以在需要时获取和控制其他系统服务,从而实现整个系统服务的协调和管理。

3 初始化电源管理

这里从代码

mActivityManagerService.initPowerManagement();

开始分析,对应代码实现如下:

//ActivityManagerServicepublic void initPowerManagement() {mStackSupervisor.initPowerManagement();mBatteryStatsService.initPowerManagement();}

接下来分成2个部分来解读

  • mStackSupervisor.initPowerManagement();
  • mBatteryStatsService.initPowerManagement();

3.1 mStackSupervisor.initPowerManagement解读

mStackSupervisor.initPowerManagement()的代码实现如下:

//ActivityStackSupervisorvoid initPowerManagement() {// 获取系统服务中的电源管理器服务PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);// 创建一个WakeLock,用于防止设备进入睡眠状态// PARTIAL_WAKE_LOCK: 用于防止CPU进入睡眠,但允许屏幕关闭// "ActivityManager-Sleep": WakeLock的标签,用于识别这个WakeLockmGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");// 创建另一个WakeLock,用于在启动活动时防止设备进入睡眠状态// "ActivityManager-Launch": WakeLock的标签mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");// 设置mLaunchingActivity这个WakeLock为非引用计数模式// 这意味着即使只有一个持有者释放了WakeLock,它也不会被释放mLaunchingActivity.setReferenceCounted(false);}

mStackSupervisor.initPowerManagement方法的主要作用是初始化ActivityManagerService中使用的电源管理相关的WakeLock。这些WakeLock用于在特定情况下防止设备进入睡眠状态,确保系统的稳定性和响应性。通过创建和管理这些WakeLock,ActivityManagerService可以更好地控制设备的电源状态,特别是在处理活动启动和睡眠过程中。

3.2 mBatteryStatsService.initPowerManagement解读

mBatteryStatsService.initPowerManagement()的代码实现如下:

//BatteryStatsServicepublic void initPowerManagement() {// 获取PowerManagerInternal服务的实例mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);// 注册当前ActivityManagerService作为低功耗模式的观察者// 这样,当系统低功耗模式发生变化时,AMS可以接收到通知并作出相应的调整。mPowerManagerInternal.registerLowPowerModeObserver(this);// 记录当前低功耗模式是否启用,这有助于系统分析和优化电源使用。mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled());// 创建并启动一个WakeupReasonThread线程,该线程用于监控和分析设备唤醒的原因// 这对于电源管理和系统性能优化很有帮助(new WakeupReasonThread()).start();}

mBatteryStatsService.initPowerManagement方法在AMS中初始化电源管理相关的功能,包括获取电源管理器内部服务、注册低功耗模式观察者、记录低功耗模式状态,以及启动一个线程来监控设备唤醒的原因。这些步骤有助于AMS更好地管理系统的电源使用,优化系统性能,同时确保设备在需要时能够及时响应用户操作。

4 将当前进程设置为系统进程

这里从代码

mActivityManagerService.setSystemProcess();

开始分析,对应代码实现如下:

//ActivityManagerServicepublic void setSystemProcess() {try {// 向ServiceManager注册ActivityManagerService,使其能被其他组件访问ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);// 向ServiceManager注册ProcessStats服务,用于监控进程统计信息ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);// 向ServiceManager注册内存信息服务ServiceManager.addService("meminfo", new MemBinder(this));// 向ServiceManager注册图形信息服务ServiceManager.addService("gfxinfo", new GraphicsBinder(this));// 向ServiceManager注册数据库信息服务ServiceManager.addService("dbinfo", new DbBinder(this));// 如果启用了监控CPU使用率,则注册CPU信息服务if (MONITOR_CPU_USAGE) {ServiceManager.addService("cpuinfo", new CpuBinder(this));}// 向ServiceManager注册权限服务ServiceManager.addService("permission", new PermissionController(this));// 获取系统应用(android)的ApplicationInfoApplicationInfo info = mContext.getPackageManager().getApplicationInfo("android", STOCK_PM_FLAGS);// 安装系统应用的ApplicationInfomSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());synchronized (this) {// 创建系统进程记录ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);app.persistent = true;  // 系统进程是持久的app.pid = MY_PID;  // 设置进程ID为当前进程IDapp.maxAdj = ProcessList.SYSTEM_ADJ;  // 设置进程的调整级别为系统级别// 激活系统进程app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);// 将系统进程记录添加到进程名称map中mProcessNames.put(app.processName, app.uid, app);synchronized (mPidsSelfLocked) {mPidsSelfLocked.put(app.pid, app);  // 将PID与进程记录关联}// 更新最近最少使用的(LRU)进程缓存updateLruProcessLocked(app, false, null);// 更新OOM调整级别updateOomAdjLocked();}} catch (PackageManager.NameNotFoundException e) {throw new RuntimeException("Unable to find android system package", e);}}

setSystemProcess方法在AMS中将当前进程设置为系统进程,并注册了一系列关键服务。这些服务包括活动管理、进程统计、内存信息、图形信息、数据库信息、CPU信息和权限控制。此外,该方法还负责创建和激活系统进程记录,确保系统进程在系统中具有最高的优先级和持久性。这个过程是Android系统启动的关键部分,确保了系统服务能够正确注册和初始化。

同时这里对 获取系统应用(android)的ApplicationInfo 和安装系统应用的ApplicationInfo做进一步的解读。

代码通过调用getPackageManager().getApplicationInfo()方法并传入参数"android",获取的是系统应用本身的ApplicationInfo。这里的"android"指的是系统应用的包名。

系统应用(android包)是Android操作系统的核心组成部分,它包含了Android框架的基本类库和系统服务。这些类库和系统服务为所有应用提供了运行时环境,包括但不限于以下内容:

  • 核心库:如android.app、android.content、android.view等。
  • 系统服务:如ActivityManagerService、WindowManagerService、PackageManagerService等。
  • 系统资源:如系统字体、颜色、样式等。

接下来对获取系统应用(android)的ApplicationInfo 和安装系统应用的ApplicationInfo 这2句话的目的和用途进行更详细的解读:

  • 初始化系统环境:这两步操作确保了系统应用的环境被正确设置,为系统服务的运行提供了必要的上下文和资源。
  • 提供系统服务访问权限:通过安装ApplicationInfo,系统服务获得了对系统应用资源的访问权限,这对于执行系统级别的任务是必要的。
  • 确保系统应用的类加载:为系统应用设置正确的类加载器,确保系统服务可以加载系统应用的类,这对于系统服务的扩展性和模块化设计至关重要。
  • 系统服务的自我识别:在Android系统中,系统服务本身也是以应用的形式运行的。通过获取和安装ApplicationInfo,系统服务能够识别自己的身份和角色,从而正确地执行其职责。

总结来说,这两步操作是系统服务启动和初始化过程的一部分,确保了系统服务能够正确地访问系统应用的资源,并为其执行系统级别的任务提供了必要的环境和权限。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

10.4学习

1.Transactional 注意事项&#xff1a; ①事务函数中不要处理耗时任务&#xff0c;会导致长期占有数据库连接。 ②事务函数中不要处理无关业务&#xff0c;防止产生异常导致事务回滚。 ●事务传播属性 ①REQUIRED&#xff08;默认属性&#xff09; 如果存在一个事务&#…

基于Springboot+VUE的二手奢侈品商城的设计与实现

一、摘要 当前&#xff0c;二手奢侈品市场持续蓬勃发展&#xff0c;吸引了越来越多的消费者。然而&#xff0c;现有的二手奢侈品交易平台在用户体验、安全性和功能方面仍存在一些问题&#xff0c;需要进一步改进。本研究旨在设计和实现一种基于Spring Boot 和 Vue 技术框架的二…

17 链表——21. 合并两个有序链表 ★

17 链表 21. 合并两个有序链表 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4] 算法设计: 合并两个有序链表,并保持有序性,可以采用迭代法和递归法两种…

Unity代码组件,代码控制旋转+RotateAround、Translate,LookAt相关

创建脚本 在Project面板创建一个Scripts文件夹&#xff0c;用于专门存放脚本&#xff0c;创建一个脚本&#xff0c;命名为RotationControl,将该脚本拖拽到Tank上&#xff0c;则Tank物体成功挂载该脚本。 双击打开脚本&#xff0c;编写脚本如下&#xff1a; using System.Coll…

国外电商系统开发-运维系统批量添加服务器

您可以把您准备的txt文件&#xff0c;安装要求的格式&#xff0c;复制粘贴到里面就可以了。注意格式&#xff01; 如果是“#” 开头的&#xff0c;则表示注释&#xff01;

746. 使用最小花费爬楼梯

文章目录 746. 使用最小花费爬楼梯思路总结 746. 使用最小花费爬楼梯 746. 使用最小花费爬楼梯 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标…

Java之队列

1. 概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性 特点&#xff1a; 队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾&#xff08;Tail/Rear&#xff09; 出队列&#xff1a;进…

【论文笔记】DKTNet: Dual-Key Transformer Network for small object detection

【引用格式】&#xff1a;Xu S, Gu J, Hua Y, et al. Dktnet: dual-key transformer network for small object detection[J]. Neurocomputing, 2023, 525: 29-41. 【网址】&#xff1a;https://cczuyiliu.github.io/pdf/DKTNet%20Dual-Key%20Transformer%20Network%20for%20s…

等额本金和等额本息是什么意思?

等额本金和等额本息是两种常见的贷款还款方式&#xff0c;它们各自有着不同的特点和适用场景。下面我将用通俗易懂的语言来解释这两种还款方式&#xff1a; 等额本金 定义&#xff1a;等额本金指的是在贷款期限内&#xff0c;每月偿还相同数额的本金&#xff0c;而利息则随着剩…

buuctf[安洵杯 2019]easy misc1

解压的一个文件夹和图片一个&#xff0c;zip压缩包有密码 FLAG IN ((√2524921X8552)15-1794)NNULLULL, ((√2524921X8552)15-1794)7 我用passware kit 2022 所以试试7位数字NNULLULL,掩码&#xff08;mask&#xff09;攻击试试 mask &#xff1a;?d?d?d?d?d?d?dNNUL…

C++【类和对象】(友元、内部类与匿名对象)

文章目录 1.友元2.内部类3.匿名对象结语 1.友元 友元提供了⼀种突破类访问限定符封装的方式&#xff0c;友元分为&#xff1a;友元函数和友元类&#xff0c;在函数声明或者类声明的前面加friend&#xff0c;并且把友元声明放到⼀个类的里面。外部友元函数可访问类的私有和保护…

图文深入理解Oracle DB企业级集中管理神器-GC

值此国庆佳节&#xff0c;深宅家中&#xff0c;闲来无事&#xff0c;就多写几篇博文。今天继续宅继续写。 本文将图文深入介绍Oracle DB企业级集中管理神器-GC&#xff1a;即Oracle Grid Control&#xff08;Oracle 企业管理器网格控制&#xff09;。 Oracle DB的牛逼之处实在太…

GS-SLAM论文阅读笔记-CaRtGS

前言 这篇文章看起来有点像Photo-slam的续作&#xff0c;行文格式和图片类型很接近&#xff0c;而且貌似是出自同一所学校的&#xff0c;所以推测可能是Photo-slam的优化与改进方法&#xff0c;接下来具体看看改进了哪些地方。 文章目录 前言1.背景介绍GS-SLAM方法总结 2.关键…

基于Keras的U-Net模型在图像分割与计数中的应用

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色&a…

【C++算法】10.滑动窗口_长度最小的子数组

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 209. 长度最小的子数组 题目描述&#xff1a; 解法 解法一&#xff1a;暴力求解&#xff08;会超时&#xff09; 暴力枚举出所有子数组的和。 查找子数组n2&#xff0…

九、怪物行为逻辑

一、怪物正常行为 1、导入资源 2、创建怪物预制体 新建一个空物体&#xff0c;作为父级、怪物作为子级 3、导入怪物动画 在怪物身上添加角色控制器和动画组件 此时怪物会有碰撞不会穿模 创建一个动画控制器&#xff0c;放入攻击状态和正常状态 并设置一个Bool值&#xff0…

[C语言]--编译和链接

文章目录 目录 文章目录 前言 一、环境介绍 二、翻译环境 1.预处理&#xff08;预编译&#xff09; 2.编译 3.汇编 4.链接 三、运行环境 前言 对编译和链接 进行简单的介绍 一、环境介绍 在ANSIC的任何⼀种实现中&#xff0c;存在两个不同的环境。 翻译环境&#xff0c;在这…

【AI学习】Mamba学习(二):线性注意力

上一篇《Mamba学习&#xff08;一&#xff09;&#xff1a;总体架构》提到&#xff0c;Transformer 模型的主要缺点是&#xff1a;自注意力机制的计算量会随着上下文长度的增加呈平方级增长。所以&#xff0c;许多次二次时间架构&#xff08;指一个函数或算法的增长速度小于二次…

使用模拟和真实的 Elasticsearch 来测试你的 Java 代码

作者&#xff1a;来自 Elastic Piotr Przybyl 在本文中&#xff0c;我们将介绍并解释两种使用 Elasticsearch 作为外部系统依赖项来测试软件的方法。我们将介绍使用模拟测试和集成测试的测试&#xff0c;展示它们之间的一些实际差异&#xff0c;并给出一些关于每种风格的提示。…

MATLAB|基于多主体主从博弈的区域综合能源系统低碳经济优化调度

目录 主要内容 程序亮点&#xff1a; 模型研究 一、综合能源模型 二、主从博弈框架 部分代码 结果一览 下载链接 主要内容 程序参考文献《基于多主体主从博弈的区域综合能源系统低碳经济优化调度》&#xff0c;采用了区域综合能源系统多主体博弈协同优化方…