Android Activity Manager Service (AMS) 深入详解及源码分析

文章目录

  • 前言
  • 一、AMS 的启动入口:SystemServer
    • 1.1 SystemServer 的初始化
    • 1.2 AMS 的初始化:startBootstrapServices
    • 1.3. ActivityManagerService 的创建与注册
      • 1.3.1 ActivityManagerService 的创建
      • 1.3.2 AMS 的构造函数
      • 1.3.3 AMS 的启动
    • 1.4 AMS 的 Binder 注册
    • 1.5 AMS 启动的调用链总结
  • 二、AMS 的核心组件结构
    • 2.1 ActivityTaskManagerService
    • 2.2 ActivityStackSupervisor
    • 2.3 进程管理(Process Management)
      • ProcessList
      • ProcessRecord
    • 2.4 广播管理(Broadcast Management)
      • BroadcastQueue
      • BroadcastRecord
    • 2.5 服务管理(Service Management)
      • ActiveServices
    • 2.6 权限管理(AppOps Management)
      • AppOpsService
    • 电量统计(Battery Stats)
      • BatteryStatsService
  • 三、Activity 启动流程详解
    • 3.1 启动流程概览
      • 1. 从 Launcher 触发启动
      • 2. 系统进程处理请求
      • 3. 应用进程启动
      • 4. Activity 创建
      • 5. 界面绘制
      • 相关源码路径
  • AMS 的常见问题及优化
    • 1. Activity 和资源管理的内存优化
    • 2. 任务栈优化(减少过度清理)
  • 总结


前言

AMS 是 Android 的核心服务,负责管理应用生命周期、进程调度、任务栈、Activity 启动与切换等功能。为了全面剖析 AMS 的工作机制,本文从启动过程、核心组件、源码分析、常见问题及优化等角度展开。


一、AMS 的启动入口:SystemServer

SystemServer 是 Android 系统启动的核心类,负责启动各种系统服务,包括 AMS。

1.1 SystemServer 的初始化

SystemServer 启动发生在 Zygote 启动后。Zygote 是 Android 的进程孵化器,创建了 SystemServer 进程。SystemServer 启动后会调用其主方法 run()。

源码路径: frameworks/base/services/java/com/android/server/SystemServer.java

public class SystemServer {public static void main(String[] args) {// 创建 SystemServer 实例并调用其 run 方法new SystemServer().run();}private void run() {// 初始化服务启动环境init();// 启动系统核心服务startBootstrapServices();startCoreServices();startOtherServices();}
}

run() 方法中的关键步骤:

  1. init():初始化运行环境。
  2. startBootstrapServices():启动引导服务,包括 AMS。
  3. startCoreServices()startOtherServices():启动其他系统服务。

1.2 AMS 的初始化:startBootstrapServices

在 startBootstrapServices() 中,AMS 的启动被显式调用。

源码路径: frameworks/base/services/java/com/android/server/SystemServer.java

关键代码:

private void startBootstrapServices() {traceBeginAndSlog("StartActivityManager");mActivityManagerService = ActivityManagerService.Lifecycle.startService(ActivityManagerService.class);traceEnd();...
}
  • traceBeginAndSlog 和 traceEnd:性能监控和日志记录,表明 AMS 启动时间点。
  • ActivityManagerService.Lifecycle.startService:AMS 的实际初始化。

1.3. ActivityManagerService 的创建与注册

1.3.1 ActivityManagerService 的创建

ActivityManagerService 是一个 SystemService 子类,生命周期由 Lifecycle 内部类管理。Lifecycle 类负责实例化 AMS 并完成注册。

源码路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

代码实现:

public static class Lifecycle extends SystemService {private final ActivityManagerService mService;public Lifecycle(Context context) {super(context);// 实例化 ActivityManagerServicemService = new ActivityManagerService(context);}@Overridepublic void onStart() {// 将 AMS 注册为 Binder 系统服务publishBinderService(Context.ACTIVITY_SERVICE, mService);// 启动 AMS 内部核心逻辑mService.start();}
}

流程解析:

  1. new ActivityManagerService(context):实例化 AMS。
  2. publishBinderService(Context.ACTIVITY_SERVICE, mService):
    将 AMS 注册为 Binder 服务,使得其他进程能够通过 Binder 调用。
    服务名:“activity”。
  3. mService.start():启动 AMS 内部模块,包括任务栈管理、进程调度模块等。

1.3.2 AMS 的构造函数

AMS 构造函数完成其基本成员变量初始化。

源码路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

关键代码:

public ActivityManagerService(Context context) {mContext = context;mActivityTaskManager = ActivityTaskManagerService.Lifecycle.startService(context);mBatteryStatsService = new BatteryStatsService(context, this);mAppOpsService = new AppOpsService(new File(dataDir, "appops.xml"), mHandler);...
}
  • AMS 内部初始化模块
  1. ActivityTaskManagerService:管理任务栈与 Activity 切换。
  2. BatteryStatsService:统计应用耗电信息。
  3. AppOpsService:管理应用操作权限。
  4. ProcessList:进程列表,用于管理系统中的进程。

1.3.3 AMS 的启动

AMS 完成基本初始化后会调用 start() 方法,启动核心逻辑。

源码路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

关键代码:

public void start() {// 初始化任务栈管理器mStackSupervisor = new ActivityStackSupervisor(this);// 初始化应用进程列表mProcessList = new ProcessList(this);// 启动任务栈调度与监控服务mStackSupervisor.init();...
}
  • 核心步骤
    1、任务栈初始化:
    创建 ActivityStackSupervisor,负责任务栈的管理与调度。
    2、进程管理初始化:
    创建 ProcessList,用于管理和调度系统中的进程。
    3、完成服务注册:
    AMS 注册完成后,可以响应系统其他组件发起的服务调用。

1.4 AMS 的 Binder 注册

AMS 启动后被注册为系统 Binder 服务。

源码路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

核心代码:

@Override
public void onStart() {// 将 ActivityManagerService 作为 Binder 系统服务注册publishBinderService(Context.ACTIVITY_SERVICE, this);
}
  • publishBinderService
    1、将 ActivityManagerService 暴露给系统的 Binder 服务管理器。
    2、通过 ServiceManager 进行统一管理。
  • 服务名:“activity”,用于应用和系统组件通过 Binder 调用 AMS。

1.5 AMS 启动的调用链总结

步骤方法源码路径
1、 SystemServer 启动SystemServer.main()frameworks/base/services/java/com/android/server/SystemServer.java
2、 启动 AMS 服务SystemServer.startBootstrapServices()frameworks/base/services/java/com/android/server/SystemServer.java
3、创建 AMS 实例ActivityManagerService.Lifecycleframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
4、AMS 构造函数初始化ActivityManagerService.()frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
5、启动核心逻辑ActivityManagerService.start()frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
6、完成 Binder 服务注册publishBinderService()frameworks/base/core/java/com/android/server/SystemService.java

二、AMS 的核心组件结构

AMS 的核心组件主要包括以下几部分:

1、任务栈管理器:ActivityTaskManagerService 和 ActivityStackSupervisor。
2、进程管理器:ProcessList 和 ProcessRecord。
3、广播机制:BroadcastQueue 和 BroadcastRecord。
4、服务管理器:ActiveServices。
5、权限管理:AppOpsService。
6、电量统计:BatteryStatsService。
每个组件在系统中的功能和职责如下:

2.1 ActivityTaskManagerService

  • 职责:管理任务栈和 Activity 的切换与调度。

  • 关联组件
    1、ActivityStackSupervisor:负责具体的任务栈操作。
    2、ActivityRecord:描述单个 Activity 的状态信息。

  • 功能
    1、管理任务栈(Task 和 ActivityStack)。
    2、处理 Activity 的启动、切换、恢复、暂停等逻辑。

关键代码:源码路径:frameworks/base/services/core/java/com/android/server/am/ActivityTaskManagerService.java

public class ActivityTaskManagerService {final ActivityStackSupervisor mStackSupervisor;public ActivityTaskManagerService(Context context) {mStackSupervisor = new ActivityStackSupervisor(this);}void startActivity() {// 调用任务栈管理器处理启动逻辑mStackSupervisor.startActivityLocked();}
}

2.2 ActivityStackSupervisor

  • 职责:具体实现任务栈的操作,例如创建新任务、管理栈顶 Activity 等。
  • 功能
    1、管理所有任务栈(ActivityStack)。
    2、调度任务栈内的 Activity 切换。
    3、维护任务栈的栈顶状态。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

public class ActivityStackSupervisor {final ArrayList<ActivityStack> mStacks = new ArrayList<>();void startActivityLocked() {// 找到目标任务栈并启动 ActivityActivityStack targetStack = getTargetStack();targetStack.startActivity();}
}

2.3 进程管理(Process Management)

ProcessList

职责:维护系统中所有进程的信息和状态。

  • 功能
    1、管理进程优先级(foreground、background 等)。
    2、清理无用进程,释放系统资源。
    3、调度系统资源分配给各进程。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/am/ProcessList.java

public final class ProcessList {// 系统中所有进程的信息final SparseArray<ProcessRecord> mProcessMap = new SparseArray<>();void updateOomAdj() {// 更新进程的优先级(OOM_ADJ)for (int i = 0; i < mProcessMap.size(); i++) {ProcessRecord app = mProcessMap.valueAt(i);computeOomAdjLocked(app);}}
}

ProcessRecord

  • 职责:表示单个进程的详细信息。
  • 功能
    1、存储进程状态(优先级、PID 等)。
    2、与 AMS 其他组件协同完成进程调度。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

public final class ProcessRecord {// 进程的 PIDint pid;// 优先级int oomAdj;// 所有运行的组件final ArrayList<ServiceRecord> services = new ArrayList<>();
}

2.4 广播管理(Broadcast Management)

BroadcastQueue

  • 职责:管理系统中的广播队列。
  • 功能
    1、区分前台广播与后台广播。
    2、调度广播发送和接收。
    3、控制广播分发的优先级。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

public final class BroadcastQueue {final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();void enqueueBroadcastLocked(BroadcastRecord r) {// 将广播添加到队列mParallelBroadcasts.add(r);}void processNextBroadcastLocked() {// 从队列取出并分发广播BroadcastRecord r = mParallelBroadcasts.remove(0);deliverBroadcast(r);}
}

BroadcastRecord

  • 职责:描述一个广播事件。
  • 功能
    存储广播的 Intent 和接收者列表。

关键代码

public final class BroadcastRecord {Intent intent;List<BroadcastReceiver> receivers;BroadcastRecord(Intent intent, List<BroadcastReceiver> receivers) {this.intent = intent;this.receivers = receivers;}
}

2.5 服务管理(Service Management)

ActiveServices

  • 职责:管理系统中所有的服务。
  • 功能
    1、启动、停止服务。
    2、维护运行中服务的状态。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {final ArrayMap<IBinder, ServiceRecord> mServiceMap = new ArrayMap<>();void startServiceLocked(ServiceRecord r) {// 启动服务逻辑r.startService();}void stopServiceLocked(ServiceRecord r) {// 停止服务逻辑r.stopService();}
}

2.6 权限管理(AppOps Management)

AppOpsService

  • 职责:控制应用的敏感操作权限。
  • 功能
    1、跟踪应用的权限使用。
    2、限制未经授权的操作。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/AppOpsService.java

public final class AppOpsService {SparseArray<UidState> mUidStates = new SparseArray<>();boolean checkOperation(int code, int uid) {UidState state = mUidStates.get(uid);return state != null && state.isOperationAllowed(code);}
}

电量统计(Battery Stats)

BatteryStatsService

  • 职责:统计系统的电量消耗。
  • 功能
    1、跟踪每个进程的耗电量。
    2、提供统计信息给其他系统服务。

关键代码: 源码路径:frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java

public final class BatteryStatsService {final BatteryStatsImpl mStats;void noteStartWakeLocked(int uid, String name) {// 记录唤醒事件mStats.noteStartWakeLocked(uid, name);}
}

三、Activity 启动流程详解

Activity 的启动流程是 Android 系统中一个核心机制,涉及多个组件的协作,包括 应用进程、AMS(ActivityManagerService)、WMS(WindowManagerService) 和 Binder 通信机制。以下是完整的 Activity 启动流程解析,结合系统源码逐步分析。

3.1 启动流程概览

从开发者调用 startActivity 方法,到 Activity 界面成功显示在屏幕上,大致可以分为以下几个阶段:
应用层:应用通过 startActivity 发起请求。
跨进程通信:ActivityManagerService 接收请求并处理。
任务栈管理:AMS 分配任务栈并通知应用创建 Activity。
窗口管理:WMS 创建窗口,启动绘制流程。
最终显示:应用进程完成 Activity 的启动,并渲染到屏幕。

我们从Launcher触发启动流程开始:

1. 从 Launcher 触发启动

1.1 用户点击事件
用户点击图标时,Launcher 会捕获点击事件并调用 startActivity 方法。

关键代码:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

// 点击事件触发
@Override
public void onClick(View v) {Intent intent = ...;  // 包含应用信息的 IntentstartActivitySafely(intent);
}// 安全启动 Activity
private boolean startActivitySafely(Intent intent) {try {startActivity(intent);  // 调用 Activity 的 startActivity 方法return true;} catch (ActivityNotFoundException e) {// 处理异常return false;}
}

分析
startActivity:发起对 ActivityManagerService(AMS)的请求,通过 Binder 调用系统服务。

2. 系统进程处理请求

AMS 接收请求
点击图标后,AMS 通过 startActivity 方法接收请求,负责任务栈管理和进程启动。

关键代码
frameworks/base/services/core/java/com/android/server/am/ActivityTaskManagerService.java

@Override
public int startActivity(IApplicationThread caller, Intent intent, ...) {// 启动请求进入 ActivityStarterreturn mActivityStartController.obtainStarter(intent, ...).execute();
}

1. 任务栈分配
AMS 检查该应用是否已经运行,并决定是否复用现有任务栈(Task),或者新建一个任务栈。

任务栈分配代码
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

private int startActivityUnchecked() {ActivityStack stack = mSupervisor.resolveTaskForActivity(...);stack.startActivityLocked(...);
}

2. 进程检查
如果应用未运行,AMS 会启动应用进程。

3. 应用进程启动

Zygote 创建进程
AMS 请求 Zygote 创建新的应用进程。Zygote 是 Android 的进程孵化器,用于 fork 出新的应用进程。
关键代码
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

private boolean startProcessLocked(...) {// 向 Zygote 发送进程启动请求Process.start(...);
}

Zygote 处理流程:
1、接收到 fork 请求后,创建新的应用进程。
2、启动 ActivityThread,进入应用主线程。

4. Activity 创建

1、AMS 通知应用进程
进程启动后,AMS 通过 ApplicationThread 调用 ActivityThread 的 scheduleLaunchActivity,通知应用启动 Activity。

关键代码
frameworks/base/core/java/android/app/ActivityThread.java

public void scheduleLaunchActivity(Intent intent, ...) {sendMessage(H.LAUNCH_ACTIVITY, r);  // 发送启动消息
}private void handleLaunchActivity(ActivityClientRecord r, ...) {// 核心启动逻辑Activity activity = performLaunchActivity(r);activity.performStart();  // 调用 onStart
}

2. Activity 生命周期回调

  • performLaunchActivity 方法完成以下操作:
    1、加载目标 Activity 类并实例化。
    2、调用 onCreate、onStart 等生命周期方法。
    关键代码:
private Activity performLaunchActivity(ActivityClientRecord r, ...) {// 创建 Activity 实例Activity activity = mInstrumentation.newActivity(...);// 调用 Activity 的 onCreate 方法activity.performCreate(r.state);return activity;
}

5. 界面绘制

1. 创建窗口
Activity 完成初始化后,ActivityThread 请求 WindowManagerService 创建窗口。

关键代码
frameworks/base/core/java/android/view/WindowManagerImpl.java

public void addView(View view, ViewGroup.LayoutParams params) {mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

2. 绘制流程

  1. ViewRootImpl 初始化:负责窗口的绘制和事件分发。
  2. Surface 创建:WMS 通知 SurfaceFlinger 创建显示的 Surface。
  3. 渲染完成:通过 OpenGL 绘制界面并呈现到屏幕。

相关源码路径

Launcher:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

AMS:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityThread:frameworks/base/core/java/android/app/ActivityThread.java

WindowManagerService:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

AMS 的常见问题及优化

只是提供思路,Google已经做的很牛逼了, 大多数优化在新版本都已经做到了,把它移植到低版本的系统就好了

1. Activity 和资源管理的内存优化

问题
在大量 Activity 启动和销毁的过程中,内存泄漏和资源回收不及时是常见问题,尤其是在多次启动和销毁 Activity 时。

优化思路

  • 及时释放资源:在 Activity 或 Task 被销毁时,及时释放与其相关的资源,避免内存泄漏。
  • 使用 WeakReference:使用弱引用来管理 Activity 或 View,避免强引用导致内存泄漏。
  • 垃圾回收优化:定期进行内存清理,主动回收不再使用的资源。

源码修改:

// 使用弱引用管理 Activity
private WeakReference<Activity> mActivityReference;// 定期进行内存清理
public void cleanupUnusedResources() {for (Activity activity : mActivityStack) {if (activity == null || !activity.isRunning()) {mActivityStack.remove(activity);}}
}

2. 任务栈优化(减少过度清理)

问题
AMS 在管理任务栈时,可能会清理过度,导致应用的任务栈被不必要地清除,增加重新启动的时间和负载。

优化思路

  • 任务栈复用:在某些情况下,复用已有的任务栈,而不是每次都清理并重新创建,减少任务栈的创建和销毁操作。
  • 智能清理:根据任务的优先级和使用频率,智能清理任务栈,避免清理过多有用的任务。

源码修改

// 智能清理任务栈
private void smartClearTaskStacks() {for (Iterator<Map.Entry<Integer, ActivityStack>> it = mTaskStacks.entrySet().iterator(); it.hasNext(); ) {Map.Entry<Integer, ActivityStack> entry = it.next();ActivityStack stack = entry.getValue();if (stack.isEmpty() || !stack.isRecentlyUsed()) {it.remove();  // 清理空栈或长时间未使用的栈}}
}

总结

AMS 是 Android 系统的中枢,其源码复杂但逻辑清晰,理解其工作机制可以帮助开发者优化应用性能。通过分析源码实现,可以深入掌握 Activity 启动、任务管理、进程调度等机制。

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

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

相关文章

【模块一】kubernetes容器编排进阶实战资源对象之Configmap与Secret简介

kubernetes 资源对象详解及示例 kubernetes 的几个重要概念 资源对象&#xff1a;kubernetes基于声明式API&#xff0c;和资源对象进行交互。 yaml文件&#xff1a;为了方便后期管理&#xff0c;通过使用yaml文件通过API管理资源对象。 yaml必需字段&#xff1a; apiVersio…

游戏引擎学习第14天

视频参考:https://www.bilibili.com/video/BV1iNUeYEEj4/ 1. 为什么关注内存管理&#xff1f; 内存分配是潜在的失败点&#xff1a; 每次进行内存分配&#xff08;malloc、new等&#xff09;时&#xff0c;都可能失败&#xff08;例如内存不足&#xff09;。这种失败会引入不稳…

游戏引擎学习第12天

视频参考:https://www.bilibili.com/video/BV1yom9YnEWY 这节没讲什么东西&#xff0c;主要是改了一下音频的代码 后面有介绍一些alloc 和malloc,VirtualAlloc 的东西 _alloca 函数&#xff08;或 alloca&#xff09;分配的是栈内存&#xff0c;它的特点是&#xff1a; 生命周…

django——创建 Django 项目和 APP

2.创建 Django 项目和 APP 命令&#xff1a; 创建Django项目 django-admin startproject name 创建子应用 python manager.py startapp name 2.1 创建工程 在使用Flask框架时&#xff0c;项目工程目录的组织与创建是需要我们自己手动创建完成的。 在django中&#xff0c;…

OceanBase 分区表详解

1、分区表的定义 在OceanBase数据库中&#xff0c;普通的表数据可以根据预设的规则被分割并存储到不同的数据区块中&#xff0c;同一区块的数据是在一个物理存储上。这样被分区块的表被称为分区表&#xff0c;而其中的每一个独立的数据区块则被称为一个分区。 如下图所示&…

学习大数据DAY61 宽表加工

目录 模型设计 加工宽表 任务调度&#xff1a; 大表 - 把很多数据整合起来 方便后续的明细查询和指标计算 模型设计 设计 建模 设计: excel 文档去编写 建模: 使用建模工具 PowerDesigner Navicat 在线画图工具... 把表结构给绘 制出来 共享\项目课工具\pd 加工宽表 数…

uniapp微信小程序转发跳转指定页面

onShareAppMessage 是微信小程序中的一个重要函数&#xff0c;用于自定义转发内容。当用户点击右上角的菜单按钮&#xff0c;并选择“转发”时&#xff0c;会触发这个函数。开发者可以在这个函数中返回一个对象&#xff0c;用于定义分享卡片的标题、图片、路径等信息。 使用场…

Datawhale组队学习】模型减肥秘籍:模型压缩技术3——模型量化

模型量化的目的是通过将浮点运算转换为定点运算&#xff0c;以减少模型大小、内存和存储需求&#xff0c;同时加快推理速度&#xff0c;降低计算功耗&#xff0c;使得模型在低算力设备上运行更加高效&#xff0c;特别适用于嵌入式设备或移动端场景。 不同数据类型&#xff08;…

arkUI:网格布局(Grid)

arkUI&#xff1a;网格布局&#xff08;Grid&#xff09; 1 主要内容说明2 网格布局的相关内容2.1 基本使用2.1.1 源码1 &#xff08;Grid网格布局&#xff09;2.1.2 源码1运行效果 2.2 设置排列方式2.2.1 核心布局参数2.2.2 网格单元格参数&#xff08;GridItem&#xff09;2.…

Cherno OpenGL(28 ~ 33)

批量渲染-介绍 在这里我们将在一个drawcall打包多个几何体。即 batch geometry。 我们在这里将聚焦于2d渲染&#xff0c;我们如何渲染一堆2d的quads或者说rectangles呢&#xff1f; 一种情况是比如一个2d游戏有很多个tile组成&#xff0c;要去渲染这些tile&#xff1b;另一种…

网络安全之国际主流网络安全架构模型

目前&#xff0c;国际主流的网络安全架构模型主要有&#xff1a; ● 信息技术咨询公司Gartner的ASA&#xff08;Adaptive Security Architecture自适应安全架构&#xff09; ● 美国政府资助的非营利研究机构MITRE的ATT&CK&#xff08;Adversarial Tactics Techniques &…

游戏引擎学习第16天

视频参考:https://www.bilibili.com/video/BV1mEUCY8EiC/ 这些字幕讨论了编译器警告的概念以及如何在编译过程中启用和处理警告。以下是字幕的内容摘要&#xff1a; 警告的定义&#xff1a;警告是编译器用来告诉你某些地方可能存在问题&#xff0c;尽管编译器不强制要求你修复…

【Nginx从入门到精通】03 、安装部署-让虚拟机可以联网

文章目录 总结一、配置联网【Minimal 精简版】1.1、查看网络配置1.2、配置ip地址 : 修改配置文件 <font colororange>ifcfg-ens33Stage 1&#xff1a;输入指令Stage 2&#xff1a;修改参数Stage 3&#xff1a;重启网络Stage 4&#xff1a;测试上网 二、配置联网【Everyth…

【UGUI】背包的交互01(道具信息跟随鼠标+道具信息面板显示)

详细程序逻辑过程 初始化物品栏&#xff1a; 在 Awake 方法中&#xff0c;通过标签找到提示框和信息面板。 循环生成10个背包格子&#xff0c;并为每个格子设置图标和名称。 为每个格子添加 UInterMaager232 脚本&#xff0c;以便处理交互事件。 关闭提示框和信息面板&#…

MySQL45讲 第二十四讲 MySQL是怎么保证主备一致的?——阅读总结

文章目录 MySQL45讲 第二十四讲 MySQL是怎么保证主备一致的&#xff1f;——阅读总结一、MySQL 主备基本原理&#xff08;一&#xff09;主备切换流程&#xff08;二&#xff09;主备数据同步流程 二、binlog 格式及相关问题&#xff08;一&#xff09;binlog 的三种格式&#…

RSA算法原理

1、RSA加密算法介绍 2、RSA算法的基本原理 2.1、RSA密钥生成 2.2、RSA加密和解密 1、RSA加密算法介绍 简单介绍一下&#xff0c;RSA算法是现代密码学的基石之一&#xff0c;广泛应用与安全通信、数据加密和身份验证等领域。 RSA加密是一种非对称加密算法&#xff0c;由罗…

html 图片转svg 并使用svg路径来裁剪html元素

1.png转svg 工具地址: Vectorizer – 免费图像矢量化 打开svg图片,复制其中的path中的d标签的路径 查看生成的svg路径是否正确 在线SVG路径预览工具 - UU在线工具 2.在html中使用svg路径 <svg xmlns"http://www.w3.org/2000/svg" width"318px" height…

哋它亢SEO技术分析:如何提升网站在搜索引擎中的可见性

文章目录 哋它亢SEO技术分析&#xff1a;如何提升网站在搜索引擎中的可见性网站的基本情况SEO优化分析与建议1. 元数据优化2. 关键词优化3. URL结构4. 图像优化5. 移动端优化6. 网站速度7. 结构化数据&#xff08;Schema Markup&#xff09;8. 内链与外链9. 社交分享 哋它亢SEO…

Liunx-Ubuntu22.04.1系统下配置Anaconda+pycharm+pytorch-gpu环境配置

这里写自定义目录标题 Liunx-Ubuntu22.04.1系统下配置Anacondapycharmpytorch-gpu环境配置一、Anaconda3配置1.Anaconda安装2.Anaconda更新3.Anaconda删除 二、pycharm配置1.pycharm安装 三、pytorch配置 Liunx-Ubuntu22.04.1系统下配置Anacondapycharmpytorch-gpu环境配置 一…

视觉SLAM--经典视觉SLAM框架

整个视觉SLAM流程主要包括以下步骤&#xff1a; 1、传感器信息读取&#xff1a;在视觉SLAM中主要为相机图像信息的读取和预处理。 2、前端视觉里程计&#xff1a;估算相邻图像间相机的运动&#xff0c;以及局部地图的样子。 3、后端&#xff08;非线性&#xff09;优化&#…