Zygote启动流程(AndroidV)
一:背景
众所周知,Android应用及system_server基本都是由zygote fork出来的,那么zygote是如何启动的、又是如何接收fork进程的请求,接下来一步步揭秘。
二:启动流程
init进程是Android系统启动时,启动的第一个进程,其他所有进程基本都是由init进程来启动,其中也包括zygote,下面看下zygote的启动。
2.1 init进程启动zygote
init.rc里,在late-init阶段会触发zygote-start,zygote-start会启动zygote服务。在zygote服务中会启动app_process64(即zygote)并传入必要参数。
//system/core/rootdir/init.rc
on late-init...# Now we can start zygote.trigger zygote-start...//system/core/rootdir/init.rc
on zygote-start...# 启动zygote服务start zygotestart zygote_secondary//system/core/rootdir/init.zygote64.rc
#启动app_process64时传参:-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygoteclass mainpriority -20...
2.2 zygote初始化
2.2.1 AndroidRuntime.start
- 启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化
- 注册jni函数
- 调用ZygoteInit的main函数
//frameworks/base/cmds/app_main.cpp
int main(int argc, char* const argv[])
{...bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;++i; // Skip unused "parent dir" argument.//获取启动参数并根据参数初始化zygote、startSystemServer等值while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME;} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true;} else if (strcmp(arg, "--application") == 0) {application = true;} else if (strncmp(arg, "--nice-name=", 12) == 0) {niceName = (arg + 12);} else if (strncmp(arg, "--", 2) != 0) {className = arg;break;} else {--i;break;}}...if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args, zygote);...
}//frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{...bool primary_zygote = false;for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {primary_zygote = true;/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));addBootEvent("boot_progress_start");}}...//启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {return;}...//注册jni函数if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}...//将className中的.替换为/ ,转换之后slashClassName的值为"com/android/internal/os/ZygoteInit"char* slashClassName = toSlashClassName(className != NULL ? className : "");jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {...} else {//获取main函数jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {...} else {//调用ZygoteInit的main函数env->CallStaticVoidMethod(startClass, startMeth, strArray);}}...
}
2.2.2 ZygoteInit.main
- 在fork前做一些初始化工作,主要是enable DDMS
- 提前加载框架通用类和系统资源
- fork进程之前进行一次gc
- 初始化seLinux
- 初始化storage
- 创建zygote的服务端对象
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javapublic static void main(String[] argv) {ZygoteServer zygoteServer = null;...//zygote运行在单独的进程组中try {Os.setpgid(0, 0);}...Runnable caller;try {...bootTimingsTraceLog.traceBegin("ZygoteInit");//做fork前的一些初始化工作,主要是enable DDMSRuntimeInit.preForkInit();boolean startSystemServer = false;String zygoteSocketName = "zygote";String abiList = null;boolean enableLazyPreload = false;//根据传参做初始化for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if ("--enable-lazy-preload".equals(argv[i])) {enableLazyPreload = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);...if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());//提前加载框架通用类和系统资源preload(bootTimingsTraceLog);EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd(); // ZygotePreload}bootTimingsTraceLog.traceBegin("PostZygoteInitGC");//fork进程之前进行一次gcgcAndFinalize();bootTimingsTraceLog.traceEnd(); // PostZygoteInitGCbootTimingsTraceLog.traceEnd(); // ZygoteInit...//native初始化Zygote.initNativeState(isPrimaryZygote);...//创建zygote的服务端对象zygoteServer = new ZygoteServer(isPrimaryZygote);if (startSystemServer) {//fork system_server进程Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);if (r != null) {r.run();return;}}...caller = zygoteServer.runSelectLoop(abiList);}...//在单独的线程中接收来自应用的zygote请求if (caller != null) {caller.run();}}//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javastatic void preload(TimingsTraceLog bootTimingsTraceLog) {...//加载/system/etc/preloaded-classes定义的所有的类preloadClasses();...//加载frameworks/base/core/res/res/values/arrays.xml中preloaded_drawables和preloaded_color_state_lists定义的所有资源Resources.preloadResources();...//加载graphic的halnativePreloadAppProcessHALs();...//加载graphicmaybePreloadGraphicsDriver();...//加载android、jnigraphics、compiler_rt这三个共享库preloadSharedLibraries();//加载字体资源preloadTextResources();...}//frameworks/base/core/java/com/android/internal/os/Zygote.javastatic void initNativeState(boolean isPrimary) {nativeInitNativeState(isPrimary);}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jclass,jboolean is_primary) {//从环境中获取init创建的文件描述符。gZygoteSocketFD =android_get_control_socket(is_primary ? "zygote" : "zygote_secondary");...//创建用于向system_server发送未经请求的消息的socket,在app申请zygote fork进程时被调用,fork完成后关闭initUnsolSocketToSystemServer();...//初始化seLinuxgIsSecurityEnforced = security_getenforce();selinux_android_seapp_context_init();//初始化storageUnmountStorageOnInit(env);//设置高优先级if (!SetTaskProfiles(0, {})) {zygote::ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");}
}
2.2.3 ZygoteInit.forkSystemServer
- 设置启动system_server的参数,例如uid、gid、进程名称等
- 调用Linux的fork函数来实现fork system_server进程
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaprivate static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {...//设置启动system_server的参数String[] args = {"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"+ "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server","--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",};...try {...//fork system_serverpid = Zygote.forkSystemServer(...);}...//子进程if (pid == 0) {...zygoteServer.closeServerSocket();return handleSystemServerProcess(parsedArgs);}...}//frameworks/base/core/java/com/android/internal/os/Zygote.javastatic int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {ZygoteHooks.preFork();int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags, rlimits,permittedCapabilities, effectiveCapabilities);//设置线程优先级为NORM_PRIORITYThread.currentThread().setPriority(Thread.NORM_PRIORITY);//ZygoteHooks.postForkCommon是Zygote进程中的一个钩子函数,它在Zygote进程fork出子进程后被调用。这个钩子函数的作用是在子进程中执行一些初始化操作,例如创建Binder线程池和消息循环等。ZygoteHooks.postForkCommon();return pid;}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(...) {...pid_t pid = zygote::ForkCommon(env, true,fds_to_close,fds_to_ignore,true);...return pid;
}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,const std::vector<int>& fds_to_close,const std::vector<int>& fds_to_ignore,bool is_priority_fork,bool purge) {ATRACE_CALL();if (is_priority_fork) {//设置最大优先级setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);}//设置信号处理程序SetSignalHandlers();...//阻断信号BlockSignal(SIGCHLD, fail_fn);...//真正fork进程的地方,在父进程中,fork()返回新创建子进程的PID,而在子进程中,fork()返回0。pid_t pid = fork();...//解除阻断信号UnblockSignal(SIGCHLD, fail_fn);if (is_priority_fork && pid != 0) {//设置优先级为PROCESS_PRIORITY_DEFAULTsetpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);}return pid;
}
2.2.4 RuntimeInit.applicationInit
- 获取SystemServer.java类对应的ClassLoader
- 初始化时区、User-Agent等
- 开启线程池
- 调用SystemServer的main函数,开始启动系统服务等
这个时候system_server进程就启动了,开始启动系统服务等
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaprivate static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {...if (parsedArgs.mInvokeWith != null) {...} else {//获取SystemServer.java类对应的ClassLoaderClassLoader cl = getOrCreateSystemServerClassLoader();...return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);}}//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javapublic static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...//初始化时区、User-Agent等RuntimeInit.commonInit();//开启线程池ZygoteInit.nativeZygoteInit();return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);}//frameworks/base/core/java/com/android/internal/os/RuntimeInit.javaprotected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...return findStaticMain(args.startClass, args.startArgs, classLoader);}//frameworks/base/core/java/com/android/internal/os/RuntimeInit.javaprotected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {Class<?> cl;try {//获取SystemServer类cl = Class.forName(className, true, classLoader);}...Method m;try {//获取main函数m = cl.getMethod("main", new Class[] { String[].class });}...//调用SystemServer的main函数,开始启动系统服务等return new MethodAndArgsCaller(m, argv);}
2.2.5 ZygoteServer.runSelectLoop
在线程里启动一个死循环,接收请求fork的socket请求
//frameworks/base/core/java/com/android/internal/os/ZygoteServer.javaRunnable runSelectLoop(String abiList) {...while (true) {...if (pollReturnValue == 0) {...} else {...while (--pollIndex >= 0) {if (pollIndex == 0) {...} else if (pollIndex < usapPoolEventFDIndex) {try {//获取socket连接ZygoteConnection connection = peers.get(pollIndex);boolean multipleForksOK = !isUsapPoolEnabled()&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();//处理来自应用请求fork的socket请求final Runnable command =connection.processCommand(this, multipleForksOK);}...}}...}...}}
三:小结
3.1 zygote进程是否只有一个?
答:不是。
zygote进程一般都会有zygote和zygote64两个,分别用来fork32位和64位的应用,这两个进程都是在init.rc中启动的。
如果系统中有webview类应用,那么还会存在webview_zygote这个进程,用来fork webview类应用。webview_zygote进程的启动是在ProcessList的startProcess函数中判断是否是webview类型应用,如果是则会调用Process的startWebView函数,接着会判断webview_zygote进程是否存在,如果不存在则调用zygote fork出来。
3.2 是否每次应用冷启动时都要调用zygote的fork函数?
答:不是。
Android系统有usap机制,会在Android系统启动时,开启一个进程池。如果usap功能打开,当有fork请求到来时,会先从进程池中取出一个进程返回,节约启动时间。
相关文章:
Zygote启动流程(AndroidV)
一:背景 众所周知,Android应用及system_server基本都是由zygote fork出来的,那么zygote是如何启动的、又是如何接收fork进程的请求,接下来一步步揭秘。 二:启动流程 init进程是Android系统启动时,启动的第一…...
Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:智行无忧停车场管理系统(前后端源码 + 数据库 sql 脚本)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 项目介绍 1.1 项目功能 2.0 用户登录功能 3.0 首页界面 4.0 车辆信息管理功能 5.0 停车位管理功能 6.0 入场登记管理功能 7.0 预约管理功能 8.0 收费规则功能 9.0…...
岩体力学的材质-力学等属性的自动划分.
#背景: 在力学求解过程中,我们往往会对目标物体进行网格划分, 那么如何做到自动完成这个过程呢? 这里使用岩体力学中的地下岩层进行举例,这里只是简单的导入了4种界面, 复杂的可以一次性导入几十种界面,都可以计算(你能分多细,这个计算方式就可以帮你分层多细) 这里我只是导…...
注解 实现原理 详解
Java 注解实现原理详解 注解(Annotation)是 Java 提供的一种元数据机制,用于为代码元素(类、方法、字段、参数等)添加额外的信息。注解不会直接影响程序逻辑,但可以通过 工具(如编译器、运行时…...
第4章 陷入与系统调用
有三种类型的事件会让CPU停止正常执行的指令,强制切换到指定的代码,处理这些事件。一种是系统调用,当用户程序执行ecall指令来让内核为它做一些事。另一种是异常:一个指令(用户或内核)做了一些非法的事&…...
项目基于oshi库快速搭建一个cpu监控面板
后端: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-…...
力扣C语言刷题记录 (二)移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作: 更改…...
多模态大语言模型的对比
简介 文章主要对比了包括 VideoLLaMA 2 、CogVLM2-video 、MiniCPM-V等模型 目前主流的多模态视觉问答大模型,大部分采用视觉编码器、大语言模型、图像到文本特征的投影模块 目录 简介1. VideoLLaMA 21.1 网络结构1.2 STC connector具体的架构 2. MiniCPM-V 2.62.…...
关于最近od机考中--树
题目 树按照层级遍历获取非叶子结点,然后将非叶子结点以后序遍历打印。 eg 图解 只需要将1,3,4,2进行后序遍历打印:既左-右-中方式打印 最后结果如:2,3,4,1。 思路&a…...
基数排序(代码+注释)
#include <stdio.h> #include <stdlib.h>// 获取数组中的最大值 int GetMax(int* a, int n) {int max a[0];for (int i 1; i < n; i) {if (a[i] > max) {max a[i];}}return max; }// 对数组按照某个位数进行计数排序 void CountingSortForRadix(int* a, i…...
NLP 相关知识的构成
自然语言处理(Natural Language Processing, NLP) 自然语言处理相关知识 自然语言处理(Natural Language Processing, NLP)什么是自然语言处理?自然语言处理的构成1. 基本术语1.1 分词(Segmentation&#x…...
算力100问☞第20问:GPU算力的影响因素有哪些?
影响因素1:核心数量 GPU中的计算核心数量是决定其算力的关键因素之一。更多的计算核心意味着可以同时处理更多的数据和任务,从而提高整体的计算效率。例如,GPU里面的计算核心就好像是工厂里的工人。工人数量越多,同时干活儿的也就…...
C语言柔性数组
在C语言中,结构体定义数组指定长度0,sizeof时候不计入占用,实际分配时候占用为准! 也许你从来没有听说过柔性数组的概念,但其确实存在。C99规定:结构中的最后一个元素允许是未知大小的数组,这就…...
TensorFlow与PyTorch对比:哪个更适合初学者?
小贴士: 不必着急,慢慢消化每一部分。有问题就查阅示例,实践是最好的老师!别忘了,选择合适的框架才是王道!💻🔍 本文全面对比了 TensorFlow 与 PyTorch 两大深度学习框架,详细分析了它们的特点、优势及适用场景,帮助初学者做出框架选择。内容包含框架背景、代码示例…...
Windows 11 如何配置node.js
一,官网下载 官网首页 下载最新LTS版本,比较稳定,如果想探索更新的版本去探索新的nodejs功能。 1. 下载完成后,双击运行程序,点击next 2. 勾选接受协议,点击next 3. 选择自己的安装路径(默认是…...
std::reverse_iterator
std::reverse_iterator 是 C 标准库中的一个迭代器适配器(iterator adapter),它允许你以反向顺序遍历容器或序列。这个适配器通过封装一个基础迭代器(通常是正向迭代器)并提供反向的递增()和递减…...
On-Chip-Network之router微架构的物理实现
Low-Power Microarchitecture 自20世纪90年代以来,功耗一直是嵌入式芯片和高性能芯片面临的一个挑战。自2000年代中期以来,它已经成为大多数设计的主要约束。多核解决了功耗问题,由此产生的communication substrate,namely the on…...
学习threejs,使用canvas更新纹理
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️Texture 贴图 二、…...
CSS 选择器的优先级
一、基本概念 CSS 选择器的优先级决定了在样式冲突时,哪个样式规则将被应用到 HTML 元素上。通过理解 CSS 选择器的优先级,可以更好地控制网页元素的样式,避免样式冲突。 二、优先级计算规则 1. 内联样式 内联样式具有最高的优先级。 &l…...
如何将python项目导出为docker镜像
如何将python项目导出为docker镜像 前提条件步骤 1: 创建并准备 Python 项目步骤 2: 创建 `setup.py`步骤 3: 打包项目步骤 4: 创建 Dockerfile步骤 5: 构建 Docker 镜像步骤 6: 运行 Docker 容器步骤 7: 保存修改并继续开发总结要将修改后的Python代码导出为 .tar.gz 格式,并…...
微信 创建小程序码-有数量限制
获取小程序码:小程序码为圆图,有数量限制。 目录 文档 接口地址 功能描述 注意事项 请求参数 对接 获取小程序码 调用获取 小程序码示例 总结 文档 接口地址 https://api.weixin.qq.com/wxa/getwxacode?access_tokenaccess_token 功能描述 …...
桶排序(代码+注释)
#include <stdio.h> #include <stdlib.h>// 定义桶的结构 typedef struct Bucket {int* data; // 动态数组int count; // 当前存储的元素个数int capacity; // 桶的容量 } Bucket;// 初始化桶 void InitBucket(Bucket* bucket) {bucket->capacity 10; // 初…...
Python从入门到入狱
Python是从入门到入狱?这个充满调侃意味的说法在程序员圈子里流传甚广。表面看,它似乎是在嘲笑这门语言从简单易学到深陷麻烦的巨大反差,实际上却隐藏着很多值得深思的问题。要解读这个话题,得从Python的特点、使用场景以及潜在风…...
图像模糊处理
图像模糊处理 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 给定n行m列的图像各像素点的灰度值,要求用如下方法对其进行模糊化处理: 1 四周最外侧的像素点灰度值不变;…...
全面UI组件库Telerik 2024 Q4全新发布——官方宣布支持.NET 9
Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库,加快开发速度。Telerik DevCraft提供最完整的工具箱,用于构建现代和面向未来的业务应用程序,目前提供UI for ASP.NET MVC、Ken…...
请求响应:常见参数接收及封装(Json参数及路径参数)
Json参数 Json格式的数据具有轻量级、易于阅读和编写、易于解析等诸多优点。在前后端交互时,大部分情况下请求体中的数据会以JSON格式进行传递。前端的请求在请求体中携带了Json格式数据,后端程序需要对其进行解析并封装使用,而接收Json参数…...
Doge东哥wordpress主题
Doge东哥wordpress主题是一款专为中小型企业设计的WordPress外贸网站模板,它以其现代、专业且用户友好的界面,为企业提供了一个展示产品和服务的理想平台。以下是对该模板的详细描述: 首页设计概览 首页的设计简洁而不失大气,顶…...
深度学习常用指标
1. 混淆矩阵(误差矩阵) 2. 准确率(overall accuracy) 代表了所有预测正确的样本占所有预测样本总数的比例 这里分类正确代表了正样本被正确分类为正样本,负样本被正确分类为负样本 3. 平均精度(average…...
AMR移动机器人赋能制造业仓储自动化升级
在当今制造业的激烈竞争中,智能化、数字化已成为企业转型升级的关键路径。一家制造业巨头,凭借其庞大的生产体系和多个仓库资源,正以前所未有的决心和行动力,在制造业智能化浪潮中勇立潮头,开启了降本增效的新篇章。这…...
显卡(Graphics Processing Unit,GPU)比特币挖矿
1. 比特币挖矿基本原理 比特币挖矿是通过参与比特币网络的共识机制——工作量证明(Proof of Work, PoW) 来完成的。具体来说,矿工通过不断尝试不同的哈希值,以解决一个难度逐渐增大的数学问题,从而验证交易并获得比特…...
11.7【miniob】【debug】
这里的vector是实际值,而relation是指针,所以要解引用,*$1,并在最后调用其析构函数 emplace_back 和 push_back 都是用于在容器(如 std::vector)的末尾添加元素的方法,但它们的工作方式有所不同…...
力扣第89题 格雷编码
题目描述 格雷编码序列是一个二进制数字序列,其中的每两个相邻的数字只有一个二进制位不同。给定一个整数 n,表示格雷编码的位数,要求返回 n 位的格雷编码序列。 示例 1 输入: n 2输出: [0, 1, 3, 2]解释&#x…...
ros sensor_msgs::Imu详细介绍 Eigen::Vector3d 详细介绍
1.ros sensor_msgs::Imu详细介绍 sensor_msgs::Imu 是 ROS(Robot Operating System)中用于表示惯性测量单元(IMU)数据的消息类型。IMU 是一种传感器,通常用于测量物体的线性加速度、角速度和方向信息。以下是 sensor_…...
【ArcGIS微课1000例】0133:二维建筑物依据高度生成三维模型
拓展阅读:【ArcGIS Pro微课1000例】0032:创建具有指定高程Z值的矢量数据 文章目录 一、二维面要素拉伸实现三维显示二、依据高度实现要素转3D一、二维面要素拉伸实现三维显示 打开ArcScene软件,加载实验配套数据0133.rar中的建筑物.shp数据,如下图: 数据属性表中的Z为建筑…...
虚拟内存的意义
1.什么是虚拟内存 虚拟内存的基本原理是将物理内存与磁盘空间组合使用,将正在执行的程序的部分数据和代码加载到物理内存中,而不是全部加载。当程序需要访问未加载到内存的部分时,操作系统会将相关数据从磁盘中加载到内存中 2.为了解决什么…...
h5 sqlite 操作封装
参考文档 错误码 // 数据库名称 const namesjk "sl" // 存储路径 const path _doc/${name}.db/** 基本操作* 查询数据库连接状态 isOpenDatabase * 无参数* 返回 true false* * * 关闭数据库 closeDatabase* 无参数* Promise 成功/失败* * * …...
Git 详解
Git 详解 Git 是一个分布式版本控制系统,用于高效地管理项目代码的版本历史。它是目前最流行的版本控制工具之一,广泛应用于软件开发领域。Git 的分布式架构允许开发者在本地进行代码的版本管理,并与远程仓库同步,实现团队协作。…...
Redis设计与实现第17章 -- 集群 总结3(ASK错误、复制与故障转移、消息)
17.5 ASK错误 在进行重新分片期间,源节点向目标节点迁移一个槽的过程中,可能会出现这样一种情况:属于被迁移槽的一部分键值对保存在源节点里面,而另一部分键值对则保存在目标节点里面。当客户端向源节点发送一个与数据库键有关的…...
支持向量机(SVM)的解析与应用:从封闭解到时代演变 (中英双语)
中文版 支持向量机(SVM)的解析与应用:从封闭解到时代演变 什么是支持向量机(SVM)? 支持向量机(Support Vector Machine, SVM)是一种经典的监督学习算法,用于解决分类和…...
Linux 密码学的基本知识与应用技术
一、基本知识 (一)加密算法 • 对称加密算法 • 原理:对称加密使用相同的密钥进行加密和解密。例如,在Linux中常用的AES(高级加密标准)算法,发送方和接收方都需要持有相同的密钥。假设要加密…...
【力扣】2094.找出3为偶数
思路 方法一:使用Set集合 1.首先是三层for循环,遍历,并且遇到不满足的情况,便跳过,继续计算。不如前导为0,以及遍历同一个数组下标的情况 2.使用Set集合来确保答案是唯一的,使用桶来标记也是可以的 3.但是…...
【信息系统项目管理师】【综合知识】【备考知识点】第十四章 项目沟通管理
【移动端浏览】☞【信息系统项目管理师】第十四章 项目沟通管理 第十四章 项目沟通管理 (项目沟通管理)定义 项目沟通管理是确保及时、正确地产生、收集、分发、存储和最终处理项目信息所需的过程。 (项目沟通管理)组成部分 (…...
CTFshow黑盒测试刷题
web380 先扫目录 打开 报错了 先用伪协议去查看源码 之前扫到有flag.php 访问一下 就得到flag了 web381 查看一下源码 点击第三个css 藏在目录里面 web382 跟上题一样 不过访问这个页面是一个登录框 试一下弱口令 最后是admin admin888 就进去了 web383 进入这个后台 …...
抖音矩阵系统快速部署指南/抖音矩阵系统源码分发,短视频矩阵账号管理系统开发部署—
抖音矩阵系统的源码分发与短视频账号管理平台的开发部署,要求通过对接官方API来实现功能的拓展。当前开发的账号矩阵管理系统专注于提供一键式管理多个账户的能力,支持定时发布内容、自动化关键词生成以实现搜索引擎优化(SEO)和霸…...
windows文件下换行, linux上不换行 解决CR换行符替换为LF notepad++
html文件是用回车换行的,在windows电脑上,显示正常。 文件上传到linux服务器后,文件不换行了。只有一行。而且相关js插件也没法正常运行。 用notepad查看,显示尾部换行符,是CR,这就是原因。CR是不被识别的。…...
服务器数据恢复—硬盘掉线导致热备盘同步失败的RAID5阵列数据恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障&#…...
活着就好20411205
5号亲爱的朋友们,大家早上好!🌞 今天是5号,星期四,2024年12月的第五天,同时也是第49周的第四天,农历甲辰[龙]年十一月初一日。在这晨曦初露的美好时刻,愿第一缕柔和的阳光悄悄探进你…...
JDK8 下载与安装
下载安装包 官网下载 官网 找到适合的版本: 网盘下载 网盘链接 提取码: 6666 下载得到的安装包: 安装步骤 双击安装包开始安装. 安装路径不要有中文或者特殊符号如空格等. 更改安装路径: 跳出一个页面, 安装公共 JRE: 安装完成: 安装目录: 安装的公共 JRE: JDK 里面的 JR…...
基于MATLAB的信号处理工具:信号分析器
信号(或时间序列)是与特定时间相关的一系列数字或测量值,不同的行业和学科将这一与时间相关的数字序列称为信号或时间序列。生物医学或电气工程师会将其称为信号,而统计学家或金融定量分析师会使用时间序列这一术语。例如…...
Docker Compose 和 Kubernetes 之间的区别?
一、简介🎀 1.1 Docker Compose Docker Compose 是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排,可以管理多个 Docker 容器组成一个应用。你只需定义一个 YAML 格式的配置文件 docker-compose.yml ,即可创建并…...