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

news2024/11/30 2:27:18

该系列文章总纲链接:专题总纲目录 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:安装系统提供的ContentProviders
		mActivityManagerService.installSystemProviders();
		
		// 初始化看门狗监控
		watchdog.init(context, mActivityManagerService);

		// 创建WindowManagerService服务
		wm = WindowManagerService.main(context, inputManager,
				mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
				mActivityManagerService);

		// 关键点6:为ActivityManagerService设置WindowManager
		mActivityManagerService.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() {
			@Override
			public 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 接口。它的代码实现如下:

//ActivityManagerService
    public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }

        @Override
        public void onStart() {
            mService.start();
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }

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

//SystemServiceManager
	//...
	//关键流程step1
    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        //...
        serviceClass = (Class<SystemService>)Class.forName(className);
		//...
        return startService(serviceClass);
    }
	//关键流程step2
    public <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方法内容如下:

//ActivityManagerService
	private 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);

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

//ActivityManagerService
    public 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();

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

//ActivityManagerService
    public void initPowerManagement() {
        mStackSupervisor.initPowerManagement();
        mBatteryStatsService.initPowerManagement();
    }

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

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

3.1 mStackSupervisor.initPowerManagement解读

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

//ActivityStackSupervisor
	void initPowerManagement() {
		// 获取系统服务中的电源管理器服务
		PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);

		// 创建一个WakeLock,用于防止设备进入睡眠状态
		// PARTIAL_WAKE_LOCK: 用于防止CPU进入睡眠,但允许屏幕关闭
		// "ActivityManager-Sleep": WakeLock的标签,用于识别这个WakeLock
		mGoingToSleep = 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()的代码实现如下:

//BatteryStatsService
	public 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();

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

//ActivityManagerService
	public 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)的ApplicationInfo
			ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
					"android", STOCK_PM_FLAGS);

			// 安装系统应用的ApplicationInfo
			mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

			synchronized (this) {
				// 创建系统进程记录
				ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
				app.persistent = true;  // 系统进程是持久的
				app.pid = MY_PID;  // 设置进程ID为当前进程ID
				app.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.coloradmin.cn/o/2188920.html

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

相关文章

Solidity 存储和内存管理:深入理解与高效优化

在 Solidity 中&#xff0c;存储和内存管理是编写高效智能合约的关键组成部分。合约执行的每一步操作都可能涉及到数据的存储和读取&#xff0c;而这些操作对 gas 的消耗有很大影响。因此&#xff0c;理解 Solidity 的存储模型以及如何优化数据的管理对于合约的安全性、性能和成…

pytorch之梯度累加

1.什么是梯度&#xff1f; 梯度可以理解为一个多变量函数的变化率&#xff0c;它告诉我们在某一点上&#xff0c;函数的输出如何随输入的变化而变化。更直观地说&#xff0c;梯度指示了最优化方向。 在机器学习中的作用&#xff1a;在训练模型时&#xff0c;我们的目标是最小…

day2网络编程项目的框架

基于终端的 UDP云聊天系统 开发环境 Linux 系统GCCUDPmakefilesqlite3 功能描述 通过 UDP 网络使服务器与客户端进行通信吗&#xff0c;从而实现云聊天。 Sqlite数据库 用户在加入聊天室前&#xff0c;需要先进行用户登录或注册操作&#xff0c;并将注册的用户信息&#xf…

P4、P4D、HelixSwarm 各种技术问题咨询

多年大型项目P4仓库运维经验&#xff0c;为你解决各种部署以及标准工业化流程问题。 Perforce 官网SDPHelixCore GuideHelixSwarm GuideHelixSwarm Download

SpringBoot基础(三):Logback日志

SpringBoot基础系列文章 SpringBoot基础(一)&#xff1a;快速入门 SpringBoot基础(二)&#xff1a;配置文件详解 SpringBoot基础(三)&#xff1a;Logback日志 目录 一、日志依赖二、日志格式1、记录日志2、默认输出格式3、springboot默认日志配置 三、日志级别1、基础设置2、…

家长们,你们认为孩子沉迷游戏严重还是沉迷Linux严重呢

matrix禁食 ​ 计算机技术与软件专业技术资格证持证人 ​ 关注 谢邀 Hieronymus no-sh 218 人赞同了该回答 十年前&#xff0c;你还能得到一个自己能控制的计算机系统&#xff0c;现在&#xff0c;窗口期早走过了。普通人不懂软件&#xff0c;但因该懂人心啊&#xff0c;人心一…

使用Apifox创建接口文档,部署第一个简单的基于Vue+Axios的前端项目

前言 在当今软件开发的过程中&#xff0c;接口文档的创建至关重要&#xff0c;它不仅能够帮助开发人员更好地理解系统架构&#xff0c;还能确保前后端开发的有效协同。Apifox作为一款集API文档管理、接口调试、Mock数据模拟为一体的工具&#xff0c;能够大幅度提高开发效率。在…

武汉自闭症儿童寄宿学校:开启学习与成长的新篇章

武汉与广州的自闭症教育之光&#xff1a;星贝育园开启学习与成长新篇章 在自闭症儿童教育的广阔领域&#xff0c;寄宿学校以其独特的教育模式和全方位的关怀&#xff0c;为这些特殊孩子提供了学习、成长与融入社会的宝贵机会。虽然本文标题提及了武汉自闭症儿童寄宿学校&#…

【HTML+CSS】仿电子美学打造响应式留言板

创建一个响应式的留言板 在这篇文章中&#xff0c;我们将学习如何创建一个简单而美观的留言板&#xff0c;它将包括基本的样式和动画效果&#xff0c;以及响应式设计&#xff0c;确保在不同设备上都能良好显示。 HTML 结构 首先&#xff0c;我们创建基本的HTML结构。留言板由…

8646 基数排序

### 思路 基数排序是一种非比较型排序算法&#xff0c;通过逐位&#xff08;从最低位到最高位&#xff09;对数字进行排序。每次分配和收集后输出当前排序结果。 ### 伪代码 1. 读取输入的待排序关键字个数n。 2. 读取n个待排序关键字并存储在数组中。 3. 对数组进行基数排序&…

MinIO 在windows环境下载和安装

目录 1.MinIO&#xff08;windows&#xff09;下载链接&#xff1a; 2. 启动MinIO &#xff08;1&#xff09;直接启动MinIo &#xff08;2&#xff09;指定端口号启动MinIo 3.通过创建.bat文件帮助启动MinIO 1.MinIO&#xff08;windows&#xff09;下载链接&#xff1a;…

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

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

Python数据可视化--Matplotlib--入门

我生性自由散漫&#xff0c;不喜欢拘束。我谁也不爱&#xff0c;谁也不恨。我没有欺骗这个&#xff0c;追求那个&#xff1b;没有把这个取笑&#xff0c;那个玩弄。我有自己的消遣。 -- 塞万提斯 《堂吉诃德》 Matplotlib介绍 1. Matplotlib 是 Python 中常用的 2D 绘图库&a…

ArkTS语法

一、声明 格式:关键字 变量/常量名 : 类型注释 = 值 变量声明 let count : number = 0; count = 40; 常量声明 const MAX_COUNT : number = 100; 二、数据类型 基本数据类型:string、number、boolean等 引用数据类型:Object、Array、自定义类等 …

【笔记】选择题笔记+数据结构笔记

文章目录 2014 41方法一先序遍历方法二 连通分量是极大连通子图 一个连通图的生成树是一个极小连通子图 无向图的邻接表中&#xff0c;第i个顶点的度为第i个链表中的结点数 邻接表和邻接矩阵对不同的操作各有优势。 最短路径算法: 单源最短路径 已知图G(V,E)&#xff0c;我们…

深入理解Linux内核网络(二):内核与用户进程的协作

内核在协议栈接收处理完输入包以后&#xff0c;要能通知到用户进程&#xff0c;让用户进程能够收到并处理这些数据。进程和内核配合有很多种方案&#xff0c;第一种是同步阻塞的方案&#xff0c;第二种是多路复用方案。本文以epoll为例 部分内容来源于 《深入理解Linux网络》、…

认知杂谈72《别让梦想只是梦!7步跃过现实高墙的终极攻略!》

内容摘要&#xff1a;         梦想的实现是一场与现实的较量&#xff0c;需要坚持和突破。学习路线图对于掌握技能至关重要&#xff0c;如学编程应从基础语法开始&#xff0c;逐步深入。 面对难题&#xff0c;积极搜索、提问和实践是关键。坚持和专注是成功的核心&#…

《Windows PE》4.1.3 IAT函数地址表

IAT&#xff08;Import Address Table&#xff09;表又称为函数地址表&#xff0c;是Windows可执行文件中的一个重要数据结构&#xff0c;用于存储导入函数的实际入口地址。 在可执行文件中&#xff0c;当一个模块需要调用另一个模块中的函数时&#xff0c;通常会使用导入函数…

十、敌人锁定

方法&#xff1a;通过寻找最近的敌人&#xff0c;使玩家的面朝向始终朝向敌人&#xff0c;进行攻击 1、代码 在这个方法中使用的是局部变量&#xff0c;作为临时声明和引用 public void SetActorAttackRotation() {Enemys GameObject.FindGameObjectsWithTag("Enemy&qu…