Android 12.0进程保活白名单功能实现

        在Android 12.0系统中,实现进程保活白名单功能是为了确保某些重要的应用程序即使进入后台也能长时间保持运行状态,不被系统自动杀死。这一功能的实现涉及多个核心类和文件,以下是具体的实现步骤和核心功能分析:  

一、实现步骤 

1.1 在IActivityManager.aidl中增加接口:

        需要在IActivityManager.aidl文件中增加与进程白名单相关的接口,例如void addWhiteListApp(String packageName)用于添加应用到白名单,void removeWhiteListApp(String packageName)用于从白名单中移除应用。

1.2 在ActivityManager.java中提供接口给应用调用:

        在ActivityManager.java文件中,需要实现上述接口,使得应用可以通过ActivityManager对象调用这些接口来操作进程白名单。

1.3 在ActivityManagerService.java中实现接口逻辑:

        在ActivityManagerService.java文件中,需要实现接口的具体逻辑,包括将应用添加到白名单或从白名单中移除,以及确保在系统杀进程时不杀死白名单中的进程。

1.4 在ActivityStackSupervisor和OomAdjuster.java中处理白名单进程:

        在ActivityStackSupervisor.java和OomAdjuster.java文件中,需要添加对白名单进程的处理逻辑。例如,在OomAdjuster.java中,可以修改进程的OOM(Out Of Memory)调整策略,以确保白名单中的进程在内存不足时不会被优先杀死。

二、涉及文件类路径

      frameworks/base/core/java/android/app/IActivityManager.aidlframeworks/base/core/java/android/app/ActivityManager.javaframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.javaframeworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.javaframeworks/base/services/core/java/com/android/server/am/OomAdjuster.java

三、具体实现

  3.1 app进程保活白名单功能实现的核心功能实现和分析

   3.1.1在lActivityManager.aidl@中新增进程白名单的接口

       void killUidForPermissionChange(int appId, int userId, String reason);boolean enableAppFreezer(in boolean enable);+    List<String> getWhiteAppProcessList();+    void setWhiteAppProcessList(in List<String> whiteAppProcessList);

 3.1.2在ActivityManager.java中增加白名单接口给app调用

       public List<String> getWhiteAppProcessList() {try {return getService().getWhiteAppProcessList();} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}public void setWhiteAppProcessList(List<String> whiteAppProcessList) {try {getService().setWhiteAppList(whiteAppProcessList);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

在ActivityManagerjava中增加这两个关于app进程白名单的接口,通过调用ActivityManagerService.java的白名单接口来设置app进程白名单实现保活app进程。

3.2 ActivityManagerService.java中实现lActivityManager.aidl的白名单接口

  1.实现保活白名单接口public class ActivityManagerService extends IActivityManager.Stubimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {private List<String> mWhiteAppProcessList = new ArrayList<String>();public void setWindowManager(WindowManagerService wm) {synchronized (this) {mWindowManager = wm;mWmInternal = LocalServices.getService(WindowManagerInternal.class);mActivityTaskManager.setWindowManager(wm);}}public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) {mUsageStatsService = usageStatsManager;mActivityTaskManager.setUsageStatsManager(usageStatsManager);}//add core startprivate List<String> mWhiteAppProcessList;@Overridepublic List<String> getWhiteAppProcessList() {return mWhiteAppProcessList;}@Overridepublic void setWhiteAppProcessList(List<String> whiteAppProcessList) {this.mWhiteAppProcessList = whiteAppProcessList;}//add core end

从AcivityManagerService中可以看出继承了IActivityManager.Stub所以说就是IActivityManager的子类所以需要实现IAcivityManager定义的保活白名单接口接下来看下关于杀进程的相关方法.

        /*** Main function for removing an existing process from the activity manager* as a result of that process going away.  Clears out all connections* to the process.*/@GuardedBy("this")final void handleAppDiedLocked(ProcessRecord app,boolean restarting, boolean allowRestart) {int pid = app.pid;boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,false /*replacingPid*/);if (!kept && !restarting) {removeLruProcessLocked(app);if (pid > 0) {ProcessList.remove(pid);}}if (mProfileData.getProfileProc() == app) {clearProfilerLocked();}mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {Slog.w(TAG, "Crash of app " + app.processName+ " running instrumentation " + app.getActiveInstrumentation().mClass);Bundle info = new Bundle();info.putString("shortMsg", "Process crashed.");finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);});}

从handleAppDiedLocked的注释中可以看出在ActivityManagerService.java中主要是调用handleAppDiedLocked处理杀掉进程的功能的,而在cleanUpApplicationRecordLocked中主要处理杀进程的工作接下来看cleanUpApplicationRecordLocked相关进程处理的方法。

        @GuardedBy("this")final boolean cleanUpApplicationRecordLocked(ProcessRecord app,boolean restarting, boolean allowRestart, int index, boolean replacingPid) {if (index >= 0) {removeLruProcessLocked(app);ProcessList.remove(app.pid);}mProcessesToGc.remove(app);mPendingPssProcesses.remove(app);ProcessList.abortNextPssTime(app.procStateMemTracker);// Dismiss any open dialogs.app.getDialogController().clearAllErrorDialogs();app.setCrashing(false);app.setNotResponding(false);app.resetPackageList(mProcessStats);app.unlinkDeathRecipient();app.makeInactive(mProcessStats);app.waitingToKill = null;app.forcingToImportant = null;updateProcessForegroundLocked(app, false, 0, false);app.setHasForegroundActivities(false);app.hasShownUi = false;app.treatLikeActivity = false;app.hasAboveClient = false;app.setHasClientActivities(false);mServices.killServicesLocked(app, allowRestart);boolean restart = false;// Remove published content providers.for (int i = app.pubProviders.size() - 1; i >= 0; i--) {ContentProviderRecord cpr = app.pubProviders.valueAt(i);if (cpr.proc != app) {// If the hosting process record isn't really us, bail outcontinue;}final boolean alwaysRemove = app.bad || !allowRestart;final boolean inLaunching = removeDyingProviderLocked(app, cpr, alwaysRemove);if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) {// We left the provider in the launching list, need to// restart it.restart = true;}cpr.provider = null;cpr.setProcess(null);}app.pubProviders.clear();// Take care of any launching providers waiting for this process.if (cleanupAppInLaunchingProvidersLocked(app, false)) {mProcessList.noteProcessDiedLocked(app);restart = true;}// Unregister from connected content providers.if (!app.conProviders.isEmpty()) {for (int i = app.conProviders.size() - 1; i >= 0; i--) {ContentProviderConnection conn = app.conProviders.get(i);conn.provider.connections.remove(conn);stopAssociationLocked(app.uid, app.processName, conn.provider.uid,conn.provider.appInfo.longVersionCode, conn.provider.name,conn.provider.info.processName);}app.conProviders.clear();}// At this point there may be remaining entries in mLaunchingProviders// where we were the only one waiting, so they are no longer of use.// Look for these and clean up if found.// XXX Commented out for now.  Trying to figure out a way to reproduce// the actual situation to identify what is actually going on.if (false) {for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {ContentProviderRecord cpr = mLaunchingProviders.get(i);if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {synchronized (cpr) {cpr.launchingApp = null;cpr.notifyAll();}}}}skipCurrentReceiverLocked(app);// Unregister any receivers.for (int i = app.receivers.size() - 1; i >= 0; i--) {removeReceiverLocked(app.receivers.valueAt(i));}app.receivers.clear();// If the app is undergoing backup, tell the backup manager about itfinal BackupRecord backupTarget = mBackupTargets.get(app.userId);if (backupTarget != null && app.pid == backupTarget.app.pid) {if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "+ backupTarget.appInfo + " died during backup");mHandler.post(new Runnable() {@Overridepublic void run(){try {IBackupManager bm = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));bm.agentDisconnectedForUser(app.userId, app.info.packageName);} catch (RemoteException e) {// can't happen; backup manager is local}}});}for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {ProcessChangeItem item = mPendingProcessChanges.get(i);if (app.pid > 0 && item.pid == app.pid) {mPendingProcessChanges.remove(i);mAvailProcessChanges.add(item);}}mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid,null).sendToTarget();// If this is a precede instance of another process instanceallowRestart = true;synchronized (app) {if (app.mSuccessor != null) {// We don't allow restart with this ProcessRecord now,// because we have created a new one already.allowRestart = false;// If it's persistent, add the successor to mPersistentStartingProcessesif (app.isPersistent() && !app.removed) {if (mPersistentStartingProcesses.indexOf(app.mSuccessor) < 0) {mPersistentStartingProcesses.add(app.mSuccessor);}}// clean up the field so the successor's proc starter could proceed.app.mSuccessor.mPrecedence = null;app.mSuccessor = null;// Notify if anyone is waiting for it.app.notifyAll();}}// If the caller is restarting this app, then leave it in its// current lists and let the caller take care of it.if (restarting) {return false;}if (!app.isPersistent() || app.isolated) {if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,"Removing non-persistent process during cleanup: " + app);if (!replacingPid) {mProcessList.removeProcessNameLocked(app.processName, app.uid, app);}mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());} else if (!app.removed) {// This app is persistent, so we need to keep its record around.// If it is not already on the pending app list, add it there// and start a new process for it.if (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);restart = true;}}.....return false;}

在cleanUpApplicationRecordLocked中的进行进程列表遍历的时候,判断app是否清除的时候根据if (!app.isPersistent() app.isolated)
调用 mAtmlntemnal.clearHeavyWeightProcesslfEquals(app.getWindowProcesscontroler();来杀掉进程所以可以在这里增加判断添加
看是否杀掉进程
具体修改如下:

    --- a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java+++ b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java@@ -14079,8 +14079,13 @@ public class ActivityManagerService extends IActivityManager.Stubif (restarting) {return false;}--        if (!app.isPersistent() || app.isolated) {+                List<String> lists=    this.mWhiteAppProcessList;+                boolean iskeepAlive=false;+                if(lists!=null && lists.contains(app.processName)){+                        iskeepAlive=true;+                }+        if ((!app.isPersistent() || app.isolated) && !iskeepAlive) {if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,"Removing non-persistent process during cleanup: " + app);if (!replacingPid) {@@ -14097,6 +14102,7 @@ public class ActivityManagerService extends IActivityManager.Stub// This app is persistent, so we need to keep its record around.// If it is not already on the pending app list, add it there// and start a new process for it.if (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);restart = true;

3.3 ActivityStackSupervisor.java中关于任务栈中杀进程的相关功能分析

             @Overridepublic void onRecentTaskRemoved(Task task, boolean wasTrimmed, boolean killProcess) {if (wasTrimmed) {// Task was trimmed from the recent tasks list -- remove the active task record as well// since the user won't really be able to go back to itremoveTaskById(task.mTaskId, killProcess, false /* removeFromRecents */,"recent-task-trimmed");}task.removedFromRecents();}boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents,String reason) {final Task task =mRootWindowContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);if (task != null) {removeTask(task, killProcess, removeFromRecents, reason);return true;}Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);return false;}void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) {if (task.mInRemoveTask) {// Prevent recursion.return;}task.mInRemoveTask = true;try {task.performClearTask(reason);cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents);mService.getLockTaskController().clearLockedTask(task);mService.getTaskChangeNotificationController().notifyTaskStackChanged();if (task.isPersistable) {mService.notifyTaskPersisterLocked(null, true);}} finally {task.mInRemoveTask = false;}}

在AcivitvStackSupervisor.java中,关于移除栈内的app进程,主要是在onRecentTaskRemoved中通过调用removeTaskByld实现的,而removeTaskByld又是调用removeTask实现的,具体是在removeTask中处理的杀进程所以具体实现如下:

          boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents,String reason) {final Task task =mRootWindowContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);if (task != null) {//add code startComponentName component = tr.getBaseIntent().getComponent();if(component!=null){String pkg=component.getPackageName();ActivityManager am = (ActivityManager) mService.mContext.getSystemService(Context.ACTIVITY_SERVICE);List<String> list=am.getWhiteAppProcessList();if(list!=null && list.contains(pkg)){return false;}}//add code endremoveTask(task, killProcess, removeFromRecents, reason);return true;}Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);return false;}

3.4OomAdjuster.java中关于对保活白名单的分析

   +    private boolean isInWhitelist(ProcessRecord pr) {+        String pkgName = pr.info.packageName;+               List<String> mLmKillerBypassPackages = mService.getKeepAliveList();+               if(mLmKillerBypassPackages!=null && mLmKillerBypassPackages.size()>0){+                       for (String token : mLmKillerBypassPackages) {+                               if (pkgName.startsWith(token)) {+                                       return true;+                               }+                       }+               }+        return false;+    }/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */@GuardedBy("mService")private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,long nowElapsed) {boolean success = true;if (app.getCurRawAdj() != app.setRawAdj) {app.setRawAdj = app.getCurRawAdj();}int changes = 0;// don't compact during bootupif (mCachedAppOptimizer.useCompaction() && mService.mBooted) {// Cached and prev/home compactionif (app.curAdj != app.setAdj) {// Perform a minor compaction when a perceptible app becomes the prev/home app// Perform a major compaction when any app enters cached// reminder: here, setAdj is previous state, curAdj is upcoming stateif (app.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ &&(app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||app.curAdj == ProcessList.HOME_APP_ADJ)) {mCachedAppOptimizer.compactAppSome(app);} else if ((app.setAdj < ProcessList.CACHED_APP_MIN_ADJ|| app.setAdj > ProcessList.CACHED_APP_MAX_ADJ)&& app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ&& app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) {mCachedAppOptimizer.compactAppFull(app);}} else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE&& app.setAdj < ProcessList.FOREGROUND_APP_ADJ// Because these can fire independent of oom_adj/procstate changes, we need// to throttle the actual dispatch of these requests in addition to the// processing of the requests. As a result, there is throttling both here// and in CachedAppOptimizer.&& mCachedAppOptimizer.shouldCompactPersistent(app, now)) {mCachedAppOptimizer.compactAppPersistent(app);} else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE&& app.getCurProcState()== ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE&& mCachedAppOptimizer.shouldCompactBFGS(app, now)) {mCachedAppOptimizer.compactAppBfgs(app);}}if (app.curAdj != app.setAdj) {// 主要修改部分开始// 注释代码开始/*ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {String msg = "Set " + app.pid + " " + app.processName + " adj "+ app.curAdj + ": " + app.adjType;reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);}app.setAdj = app.curAdj;app.verifiedAdj = ProcessList.INVALID_ADJ;*/// 注释代码结束+            boolean isAppWhiteProcess = false;+            if(isInWhitelist(app) && (app.curAdj > ProcessList.PERSISTENT_SERVICE_ADJ))isAppWhiteProcess = true;+            if(isAppWhiteProcess){+                Slog.d(TAG,"isAppWhiteProcess");+                ProcessList.setOomAdj(app.pid, app.uid, ProcessList.PERSISTENT_SERVICE_ADJ);+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {+                    String msg = "Set " + app.pid + " " + app.processName + " adj "+                            + app.curAdj + ": " + app.adjType;+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);+                }+                app.setAdj = ProcessList.PERSISTENT_SERVICE_ADJ;+                app.verifiedAdj = ProcessList.INVALID_ADJ;+            }else{+                ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {+                    String msg = "Set " + app.pid + " " + app.processName + " adj "+                            + app.curAdj + ": " + app.adjType;+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);+                }+                app.setAdj = app.curAdj;+                app.verifiedAdj = ProcessList.INVALID_ADJ;+            }}.....return success;}

在上述的OomAdjuster.java的代码中,首选通过isInWhitelist(ProcessRecord pr)判断当前进程是否在白名单之内,然后通过设置app.setAdj和app.verifiedAdj 两个值来确保app不会被杀掉.

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

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

相关文章

面包种类图像分割系统:多层面改进

面包种类图像分割系统源码&#xff06;数据集分享 [yolov8-seg-GhostHGNetV2&#xff06;yolov8-seg-C2f-DCNV3等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Globa…

使用Llama Index与Streamlit实现一个从文本中提取专业术语和定义网页小程序

Llama Index有许多用例&#xff08;语义搜索、摘要等&#xff09;&#xff0c;并且都有很好的记录。然而&#xff0c;这并不意味着我们不能将Llama Index应用到非常具体的用例中&#xff01; 在本教程中&#xff0c;我们将介绍使用Llama Index从文本中提取专业术语和定义的设计…

Ovis: 多模态大语言模型的结构化嵌入对齐

论文题目&#xff1a;Ovis: Structural Embedding Alignment for Multimodal Large Language Model 论文地址&#xff1a;https://arxiv.org/pdf/2405.20797 github地址&#xff1a;https://github.com/AIDC-AI/Ovis/?tabreadme-ov-file 今天&#xff0c;我将分享一项重要的研…

量子机器学习:颠覆性的前沿技术

量子机器学习&#xff1a;颠覆性的前沿技术 引言 在科技日新月异的今天&#xff0c;量子计算和机器学习作为两大前沿领域&#xff0c;各自在推动科技进步中发挥着重要作用。而当这两者结合时&#xff0c;便诞生了一个全新的领域——量子机器学习&#xff08;Quantum Machine …

GCC 简介

Linux 中的编译器 GCC 的编译原理和使用详解 GCC 简介 GCC&#xff08;GNU Compiler Collection&#xff09;是一套由 GNU 开发的编程语言编译器&#xff0c;它支持多种编程语言&#xff0c;包括 C、C、Objective-C、Fortran、Ada 和 Go 等。GCC 是一个开源的工具集&#xff…

Spring Boot框架在学生宿舍管理中的应用研究

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了学生宿舍信息管理系统的开发全过程。通过分析学生宿舍信息管理系统管理的不足&#xff0c;创建了一个计算机管理学生宿舍信息管理系统的方案。文章介绍了学生宿舍…

AI读教链《为什么今年ETH对BTC表现这么拉垮?》

以太坊&#xff08;ETH&#xff09;近期表现不佳&#xff0c;主要是由于市场对其价值存储功能的信心下降&#xff0c;尤其是在比特币&#xff08;BTC&#xff09;表现强劲的背景下。ETH的市值逐渐被以Solana等新兴公链抢占&#xff0c;流失了大量用户和炒币的流量。此外&#x…

JAVA排序

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&…

跟着鸟儿学飞行?扑翼机器人的感知秘籍

大家好&#xff01;今天来了解一篇扑翼机器人的研究——《Avian-inspired embodied perception in biohybrid flapping-wing robotics》发表于《Nature Communications》。在广阔天空中&#xff0c;鸟类凭借精妙翅膀结构与敏锐感知自由翱翔&#xff0c;这一直吸引着科学家探索其…

cherry pick commit

cherry pick commit git cherry-pick 是一个 Git 命令&#xff0c;用于将特定的提交&#xff08;commit&#xff09;应用到当前分支上。这在需要从其他分支中挑选某些提交到当前分支时非常有用&#xff0c;例如当你需要修复一个 bug&#xff0c;但想只应用特定的变更&#xff…

国内大语言模型哪家更好用?

大家好&#xff0c;我是袁庭新。 过去一年&#xff0c;AI大语言模型在爆发式增长&#xff0c;呈现百家争鸣之态。国内外相关厂商积极布局&#xff0c;并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务&#xff0c;甚至对它们产…

基于物联网的智慧考场系统设计(论文+源码)

1. 功能设计 &#xff08;1&#xff09;温度监测与控制功能&#xff1a; 系统需要能够实时采集考场内的温度信息&#xff0c;通过DS18B20传感器获取准确的数据&#xff0c;并在OLED屏幕和APP上显示。当温度异常过高时&#xff0c;系统应自动启动继电器&#xff0c;模拟空调开启…

【Python】深入理解Python的列表推导式与生成器表达式:简洁与性能的权衡

引言 Python因其简洁易懂的语法和强大的标准库&#xff0c;深受开发者的喜爱。为了提升代码的简洁性与可读性&#xff0c;Python引入了许多方便的语法特性&#xff0c;其中列表推导式和生成器表达式是非常重要的工具。这两者为我们提供了优雅的方式来生成序列数据&#xff0c;…

API接口开放与安全管控 - 原理与实践

API安全是接口开放的前提条件 在API对外开放时&#xff0c;确保其安全性至关重要&#xff0c;因为API直接暴露给外部环境&#xff0c;容易成为攻击目标。一旦被恶意利用&#xff0c;可能导致数据泄露、服务滥用等严重后果。因此&#xff0c;通过API网关实施严格的接口安全管理…

用“堆”模拟实现“优先级队列”

PriorityQueue优先级队列 1. 优先级队列的概念2. 优先队列的模拟实现3 堆的概念4. 堆的存储方式5. 堆向下调整6. 堆的创建7. 堆的插入8. 堆的删除9. 用堆模拟实现优先级队列 1. 优先级队列的概念 前面我们学习了队列&#xff0c;队列是一种“先进先出”的数据结构&#xff0c;…

智慧农业大数据平台:智汇田园,数驭未来

智慧农业大数据平台 计讯物联智慧农业大数据平台是一个集管理数字化、作业自动化、生产智能化、产品绿色化、环境信息化、服务现代化于一体的多功能监管系统。它通过与硬件产品的搭配使用&#xff0c;实现对农业生产全过程的实时监测、精准控制和科学管理。该平台集成了多个数…

blender 小车建模 建模 学习笔记

一、学习blender视频教程链接 案例4&#xff1a;狂奔的小车_建模_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Bt4y1E7qn?p14&spm_id_from333.788.videopod.episodes&vd_sourced0ea58f1127eed138a4ba5421c577eb1 二、开始建模 &#xff08;1&#xff09;创…

逻辑回归与神经网络

从逻辑回归开始学习神经网络 神经网络直观上解释&#xff0c;就是由许多相互连接的圆圈组成的网络模型&#xff1a; 而逻辑回归可以看作是这个网络中的一个圆圈&#xff1a; 圆圈被称为神经元&#xff0c;整个网络被称为神经网络。 本节的任务是我们究竟如何理解具体的一个神…

华为OD机试 - 芯片资源占用(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

QT仿QQ聊天项目,第一节,创建项目并布置编辑登录界面

目录 一&#xff0c;创建项目 二&#xff0c;编辑登录界面 1&#xff0c;登录界面整体构造 2&#xff0c;登录界面的宽高 3&#xff0c;登录界面使用到的控件 4&#xff0c;登录界面中的控件所在的位置和大小 &#xff08;1&#xff09;qq图标label位置和大小 &#xff0…