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,系统服务能够识别自己的身份和角色,从而正确地执行其职责。
总结来说,这两步操作是系统服务启动和初始化过程的一部分,确保了系统服务能够正确地访问系统应用的资源,并为其执行系统级别的任务提供了必要的环境和权限。
相关文章:

Android Framework AMS(01)AMS启动及相关初始化1-4
该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要涉及systemserver启动AMS及初始化AMS相关操作。同时由于该部分内容分析过多,因此拆成2个章节,本章节是第一章节&…...

基于基于微信小程序的社区订餐系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...

[单master节点k8s部署]29.Istio流量管理(五)
测试istio熔断管理。 采用httpbin镜像和fortio镜像,其中httpbin作为服务端,fortio是请求端。这两个的配置yaml文件都在istio的samples/httpbin目录下,fortio的配置文件在samples-client目录下。 [rootmaster httpbin]# ls gateway-api ht…...

Something for 24OI
zyj老师希望我给24OI的同学们写一点东西,虽然感觉我也没有什么先进经验,还是尽力写一些主观的感受吧。 如何平衡文化课和竞赛的关系?不要以牺牲文化课的代价学习竞赛。首先,绝大多数的竞赛同学,或早或晚都会在退役后回…...

【React】事件机制
事件机制 react 基于浏览器的事件机制自身实现了一套事件机制,称为合成事件。比如:onclick -> onClick 获取原生事件:e.nativeEvent onClick 并不会将事件代理函数绑定到真实的 DOM节点上,而是将所有的事件绑定到结构的最外层…...

华为OD的职级与薪资
华为 OD 这几年随着招聘行情的日渐严峻,不少 985 高校出来的学生都开始放宽对"外包"的看法,其中华为 OD 以"待遇断层领先"的姿态成为不少求职者(不得已)的外包首选。 既然如此,我们就好好梳理一下…...

【HTML5】html5开篇基础(4)
1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…...

HTTP【网络】
文章目录 HTTPURL(Uniform Resource Lacator) HTTP协议格式HTTP的方法HTTP的状态码HTTP常见的Header HTTP 超文本传输协议,是一个简单的请求-响应协议,HTTP通常运行在TCP之上 URL(Uniform Resource Lacator) 一资源定位符,也就是通常所说的…...

MQ延迟消息:原理、实现与应用
在现代分布式系统中,消息队列(Message Queue,简称MQ)已经成为实现异步通信、解耦服务和削峰填谷的重要工具。延迟消息(Delayed Message)作为MQ的一种高级特性,允许消息在指定的延迟时间后投递到…...

计算机网络—大端序和小端序
大端序和小端序 大端序(Big-endian)和小端序(Little-endian)是指在多字节数据类型(如整数或浮点数)的存储和表示方式上的不同。以下是关于大端序和小端序的详细解释: 一、定义 大端序…...

《OpenCV 计算机视觉》—— Harris角点检测、SIFT特征检测
文章目录 一、Harris 角点检测1.基本思想2.检测步骤3.OpenCV实现 二、SIFT特征检测1. SIFT特征检测的基本原理2. SIFT特征检测的特点3. OpenCV 实现 一、Harris 角点检测 OpenCV中的Harris角点检测是一种基于图像灰度值变化的角点提取算法,它通过计算每个像素点的响…...

rtmp协议转websocketflv的去队列积压
websocket server的优点 websocket server的好处:WebSocket 服务器能够实现实时的数据推送,服务器可以主动向客户端发送数据 1 不需要客户端不断轮询。 2 不需要实现httpserver跨域。 在需要修改协议的时候比较灵活,我们发送数据的时候比较…...

Elasticsearch实战应用:构建高效搜索引擎
在大数据时代,如何高效存储和检索海量信息成为了一个重要课题。Elasticsearch作为一个开源的分布式搜索引擎,以其强大的搜索能力和灵活的扩展性,成为了许多企业和开发者的首选。本文将深入探讨Elasticsearch的实战应用,包括基本概…...

Hive数仓操作(四)
一、Hive 创建表案例一(ARRAY数组类型) 1. 准备数据文件 首先,准备一个名为 stu2.txt 的文件,文件内容示例如下: 1001 Alice fish,cat 1002 Bob dog,rabbit 1003 Charlie bird注意: …...

《C++跨平台开发:突破界限,释放无限可能》
在当今的软件开发领域,跨平台开发已成为一种重要趋势。它允许开发者编写一次代码,然后在多个不同的操作系统和硬件平台上运行,极大地提高了开发效率和软件的可扩展性。而 C作为一种强大的编程语言,也具备实现跨平台开发的能力。本…...

速盾:免备案服务器?
速盾是一家提供网络安全服务的公司,其主要产品包括CDN加速、WEB防护、WAF、DDoS防护等。在网站建设过程中,选择一个合适的服务器是非常重要的一步。传统的服务器需要备案,涉及到较多的流程和审批时间,给网站运营带来了一定的麻烦。…...

Electron获取nodejs和chrome版本信息
Electron获取nodejs和chrome版本信息 环境: electron: 30.1.1 nodejs: 20.14.0代码 $ tree . --- index.html --- index.js --- package.jsonindex.html <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>H…...

【React】setState 批量更新
setState 批量更新的过程 React 的 setState 调用是异步的。为了性能原因,React 会将多个 setState 调用合并成一次批量更新。具体过程如下: 1)React 先将调用的每个 setState 所产生的更新对象存储在一个队列中。 2)在所有的同步…...

微信小程序开发日记第二天
坚持在各个平台更新自己写小程序的心得体会,在百度贴吧和csdn更新自己的小程序日记,同时也是个体不断地对于云技术的开发和成长,进行提升!不断地将开源开放创新思维运用到自己的小程序当中,小程序制作的关键就是&#…...

如果您忘记了 Apple ID 和密码,按照指南可重新进入您的设备
即使您的 iPhone 或 iPad 由于各种原因被锁定或禁用,也可以使用 iTunes、“查找我的”、Apple 支持和 iCloud 解锁您的设备。但是,此过程需要您的 Apple ID 和密码来验证所有权并移除激活锁。如果您忘记了 Apple ID 和密码,请按照我们的指南重…...

Top4免费音频剪辑软件大比拼,2024年你选哪一款?
现在我们生活在一个数字化的时代,音频内容对我们来说很重要。不管是给自己拍的视频配背景音乐、整理开会时的录音,还是自己写歌,有个好用的音频剪辑软件都特别重要。今天,我要给大家介绍几款特别好用的音频剪辑软件免费的…...

基于SSM的电影院售票系统设计与实现
文未可获取一份本项目的java源码和数据库参考。 前言 近些年的电影在人们文娱活动中占据重要地位,另外,由于人们的生活越来越富有,越来越多的人们不再选择在家里看电影,而是选择去电影院看电影。但是,以往的售票方式是…...

uniapp 必须掌握的细节
1.使用watch实现实时监控的效果 例如:实时监测手机号码的示例 // 实时监测手机号码 watch(() > UserRegisterForm.value.phone, (newPhone) > {// 简单的手机号码正则表达式验证const phoneRegex /^1[3-9]\d{9}$/;tips.value.tipPhone !phoneRegex.test(n…...

JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
目录 Dialog对话框 介绍 使用 实际效果 Form表单 介绍 使用 实际效果 Dialog对话框 介绍 Dialog对话框:在保留当前页面状态的情况下,告知用户并承载相关操作。 Dialog 对话框组件可以在保留当前页面信息的状态下弹出一个对话框,并…...

一个月学会Java 第2天 认识类与对象
Day2 认识类与对象 第一章 初识类 经过一个程序的编写,应该对程序的结构有点好奇了吧,如果你有基础,接下来的肯定非常的易懂,如果你没有基础也没有关系,反复琢磨一下也就懂了😆 我们来重复一下第一个程序 …...

【WRF数据准备】MODIS静态地理数据下载及制备
【WRF数据准备】MODIS静态地理数据下载及制备 MODIS数据介绍数据下载数据拼接MRT工具介绍基于MRT软件完成数据拼接 格式转换:tif文件转二进制格式编写INDEX修改GEOGRID.TBL以及namelist.wps修改GEOGRID.TBL修改namelist.wps 参考 MODIS数据介绍 MODIS-MCD12Q1 v061…...

MySQL数据库——索引
目录 什么是索引(Index)? 怎样加索引? 索引的特点 索引类型 主键索引(Primary Key) 辅助索引(二级索引) 聚集索引和非聚集索引 聚集索引 非聚集索引 单列索引和联合索引 单列索引 联合索引 创…...

【SpringCloud】服务注册/服务发现-Eureka
服务注册/服务发现-Eureka 1. 背景1.1 问题描述1.2 解决思路1.3 什么是注册中⼼1.4 CAP理论1.5 常⻅的注册中⼼ 2. Eureka 介绍3. 搭建Eureka Server 1. 背景 1.1 问题描述 上个章节的例⼦中可以看到, 远程调⽤时, 我们的URL是写死的 String url "http://127.0.0.1:90…...

让你的Github Profile高大时尚!
目录 前言 正文 GitHub Profile 特点: GitHub Actions 核心概念: 应用场景: RSS RSS的主要特点: 使用场景: RSS的工作原理: 关于Github Readme Card 关于Github贡献的3D图 关于个人最新博文的获取 关于代码…...

ElasticSearch备考 -- Multi match
一、题目 索引task有3个字段a、b、c,写一个查询去匹配这三个字段为mom,其中b的字段评分比a、c字段大一倍,将他们的分数相加作为最后的总分数 二、思考 通过题目要求对多个字段进行匹配查询,可以考虑multi match、bool query操作。…...