鸿蒙轻内核A核源码分析系列七 进程管理 (3)

本文记录下进程相关的初始化函数,如OsSystemProcessCreate、OsProcessInit、OsProcessCreateInit、OsUserInitProcess、OsDeInitPCB、OsUserInitProcessStart等。

1、LiteOS-A内核进程创建初始化通用函数

先看看一些内部函数,不管是初始化用户态进程还是内核态进程,都会使用这些函数,包含进程控制块初始化函数OsInitPCB、进程控制块初始化恢复函数OsDeInitPCB

1.1 进程控制块初始化函数OsInitPCB

进程控制块初始化函数OsInitPCB需要3个参数,第一个参数processCB是进程块指针,第二个参数为进程模式mode,分为内核态进程OS_KERNEL_MODE和用户态进程OS_USER_MODE。第三个参数用于设置进程名称。返回值为初始化成功LOS_OK还是失败LOS_ENOMEM。看下代码,⑴处设置进程控制块的信息,用户态进程还是内核态进程,进程状态设置为初始化状态,线程组编号设置为无效值,设置为默认掩码,定时器编号设置为无效值。⑵处初始化进程的双向链表。如果系统配置支持虚拟内存,则执行⑶判断初始化的进程是否为用户态进程,如果是用户态进程,则创建虚拟地址空间,如果创建失败,则把进程状态设置为未使用状态,然后返回错误码。⑷处表示如果是内核态进程,则指定进程的内核进程虚拟地址空间。有关虚拟地址空间的信息,请参考之前的系列文章。

如果执行CPUP特性,则执行⑸处代码,则为CPUP结构体申请内存空间。⑹处,如果开启了LOSCFG_SECURITY_VID,则V初始化ID映射链表。⑺处,如果开启了安全能力LOSCFG_SECURITY_CAPABILITY,则进行相应的初始化。⑻处为进程设置一个名称。

    STATIC UINT32 OsInitPCB(LosProcessCB *processCB, UINT32 mode, const CHAR *name){
⑴      processCB->processMode = mode;processCB->processStatus = OS_PROCESS_STATUS_INIT;processCB->parentProcessID = OS_INVALID_VALUE;processCB->threadGroupID = OS_INVALID_VALUE;processCB->umask = OS_PROCESS_DEFAULT_UMASK;processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;⑵      LOS_ListInit(&processCB->threadSiblingList);LOS_ListInit(&processCB->childrenList);LOS_ListInit(&processCB->exitChildList);LOS_ListInit(&(processCB->waitList));#ifdef LOSCFG_KERNEL_VM
⑶      if (OsProcessIsUserMode(processCB)) {processCB->vmSpace = OsCreateUserVmSpace();if (processCB->vmSpace == NULL) {processCB->processStatus = OS_PROCESS_FLAG_UNUSED;return LOS_ENOMEM;}} else {
⑷          processCB->vmSpace = LOS_GetKVmSpace();}#endif#ifdef LOSCFG_KERNEL_CPUP
⑸      processCB->processCpup = (OsCpupBase *)LOS_MemAlloc(m_aucSysMem1, sizeof(OsCpupBase));if (processCB->processCpup == NULL) {return LOS_ENOMEM;}(VOID)memset_s(processCB->processCpup, sizeof(OsCpupBase), 0, sizeof(OsCpupBase));#endif#ifdef LOSCFG_SECURITY_VID
⑹      status_t status = VidMapListInit(processCB);if (status != LOS_OK) {return LOS_ENOMEM;}#endif⑺  #ifdef LOSCFG_SECURITY_CAPABILITYOsInitCapability(processCB);#endif⑻      if (OsSetProcessName(processCB, name) != LOS_OK) {return LOS_ENOMEM;}return LOS_OK;}

1.2 进程控制块初始化恢复函数OsDeInitPCB

在创建进程时,会执行该函数,恢复进程控制块信息到初始化之前的状态。⑴处释放进程的资源,包含地址空间、文件、安全能力、定时器等占用的内存。如果存在父进程,则执行⑵从父进程的兄弟列表上删除。如果进程属于进程组,则从进程组中退出。然后执行⑷设置进程状态为退出态,把进程放入待回收链表中。

    STATIC VOID OsDeInitPCB(LosProcessCB *processCB){UINT32 intSave;ProcessGroup *group = NULL;if (processCB == NULL) {return;}⑴      OsProcessResourcesToFree(processCB);SCHEDULER_LOCK(intSave);if (processCB->parentProcessID != OS_INVALID_VALUE) {
⑵          LOS_ListDelete(&processCB->siblingList);processCB->parentProcessID = OS_INVALID_VALUE;}⑶      if (processCB->group != NULL) {OsExitProcessGroup(processCB, &group);}⑷      processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;processCB->processStatus |= OS_PROCESS_FLAG_EXIT;LOS_ListHeadInsert(&g_processRecycleList, &processCB->pendList);SCHEDULER_UNLOCK(intSave);(VOID)LOS_MemFree(m_aucSysMem1, group);OsWriteResourceEvent(OS_RESOURCE_EVENT_FREE);return;}

2、 LiteOS-A内核系统进程创建函数OsSystemProcessCreate

系统进程创建函数OsSystemProcessCreate在文件kernel\common\los_config.c中被调用,在系统启动阶段创建系统进程。该函数又调用OsProcessInit,我们首先看下函数OsProcessInit。

2.1 进程初始化函数OsProcessInit

进程初始化函数OsProcessInit为进程控制块申请内存,初始化进程相关的进程链表。我们看下代码,⑴处获取配置的进程最大数值,然后计算需要的内存大小。⑵处申请内存,初始化申请的内存块。⑶处初始化空闲进程双向链表和待回收进程双向链表。
⑷处初始化每一个进程,社区进程编号、进程状态,然后把每一个进程放到空闲进程链表里。⑸处设置Idle进程编号为0,用户根进程编号为1,系统根进程编号为2,然后执行LOS_ListDelete把这3个进程从阻塞链表上删除。

    STATIC UINT32 OsProcessInit(VOID){UINT32 index;UINT32 size;⑴      g_processMaxNum = LOSCFG_BASE_CORE_PROCESS_LIMIT;size = g_processMaxNum * sizeof(LosProcessCB);⑵      g_processCBArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);if (g_processCBArray == NULL) {return LOS_NOK;}(VOID)memset_s(g_processCBArray, size, 0, size);⑶      LOS_ListInit(&g_freeProcess);LOS_ListInit(&g_processRecycleList);⑷      for (index = 0; index < g_processMaxNum; index++) {g_processCBArray[index].processID = index;g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);}⑸      g_kernelIdleProcess = 0; /* 0: The idle process ID of the kernel-mode process is fixed at 0 */LOS_ListDelete(&OS_PCB_FROM_PID(g_kernelIdleProcess)->pendList);g_userInitProcess = 1; /* 1: The root process ID of the user-mode process is fixed at 1 */LOS_ListDelete(&OS_PCB_FROM_PID(g_userInitProcess)->pendList);g_kernelInitProcess = 2; /* 2: The root process ID of the kernel-mode process is fixed at 2 */LOS_ListDelete(&OS_PCB_FROM_PID(g_kernelInitProcess)->pendList);return LOS_OK;}

2.2 进程创建初始化函数OsProcessCreateInit

该函数用于创建进程时的一些初始化操作,主要是文件系统、安全能力、进程组等等。需要3个参数,分别是进程控制块指针,标记用户态还是内核态进程的flags,进程名称name。首先执行⑴调用OsInitPCB()对进程控制块进行初始化,然后,如果配置支持了虚拟文件系统VFS,则执行⑵为进程分别文件。⑶处根据进程号创建进程组。如果支持安全能力,则执行⑷创建用户。如果初始化失败,会执行⑸恢复进程控制块到初始化之前的状态。

    STATIC UINT32 OsProcessCreateInit(LosProcessCB *processCB, UINT32 flags, const CHAR *name){ProcessGroup *group = NULL;
⑴      UINT32 ret = OsInitPCB(processCB, flags, name);if (ret != LOS_OK) {goto EXIT;}#ifdef LOSCFG_FS_VFS
⑵      processCB->files = alloc_files();if (processCB->files == NULL) {ret = LOS_ENOMEM;goto EXIT;}#endif⑶      group = OsCreateProcessGroup(processCB->processID);if (group == NULL) {ret = LOS_ENOMEM;goto EXIT;}#ifdef LOSCFG_SECURITY_CAPABILITY
⑷      processCB->user = OsCreateUser(0, 0, 1);if (processCB->user == NULL) {ret = LOS_ENOMEM;goto EXIT;}#endifreturn LOS_OK;EXIT:
⑸      OsDeInitPCB(processCB);return ret;}

2.3 系统进程创建函数OsSystemProcessCreate

接下来,我们看看系统进程创建函数OsSystemProcessCreate的源代码。⑴处开始先后调用OsProcessInit、OsProcessCreateInit初始化内核态根进程,⑵处进程的状态不再是初始化状态。⑶处从内核进程获取全局进程组指针g_processGroup,然后初始化进程组的双向链表。这样看来,所有的进程组都会挂载到内核进程的进程组节点上。⑷处初始化内核空闲进程,内核空闲进程的父进程也是内核态根进程,插入到进程组链表,设置空闲进程的状态不再是初始化状态。执行⑸创建空闲任务,然后设置空闲进程的线程组编号为空闲线程编号。

    LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID){
⑴      UINT32 ret = OsProcessInit();if (ret != LOS_OK) {return ret;}LosProcessCB *kerInitProcess = OS_PCB_FROM_PID(g_kernelInitProcess);ret = OsProcessCreateInit(kerInitProcess, OS_KERNEL_MODE, "KProcess");if (ret != LOS_OK) {return ret;}⑵      kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;
⑶      g_processGroup = kerInitProcess->group;LOS_ListInit(&g_processGroup->groupList);⑷      LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, "KIdle");if (ret != LOS_OK) {return ret;}idleProcess->parentProcessID = kerInitProcess->processID;LOS_ListTailInsert(&kerInitProcess->childrenList, &idleProcess->siblingList);idleProcess->group = kerInitProcess->group;LOS_ListTailInsert(&kerInitProcess->group->processList, &idleProcess->subordinateGroupList);#ifdef LOSCFG_SECURITY_CAPABILITYidleProcess->user = kerInitProcess->user;#endif#ifdef LOSCFG_FS_VFSidleProcess->files = kerInitProcess->files;#endifidleProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;⑸      ret = OsIdleTaskCreate();if (ret != LOS_OK) {return ret;}idleProcess->threadGroupID = OsGetIdleTaskId();return LOS_OK;}

3. LiteOS-A内核用户进程创建函数OsUserInitProcess

系统启动阶段,OsUserInitProcess启动init进程。该函数在device开发板目录下系统初始化文件中调用,如system_init.c等等。该函数需要开启LOSCFG_KERNEL_DYNLOAD宏,否则函数体内容为空。在阅读函数OsUserInitProcess的源码前,先看看该函数调用的其他函数,如OsLoadUserInit、OsUserInitStackAlloc、OsUserInitProcessStart等等。

3.1 加载用户初始化数据函数OsLoadUserInit

该函数用于加载用户数据。⑴处从链接脚本获取text、bss的开启和结束地址,然后计算bss段、初始化段的大小。⑵处进行一些必要的校验,是否针对内存页对齐,内存段长度是否合理等。然后执行⑶,申请物理内存页,然后把用户初始化数据复制到申请的内存页。⑷处进行虚实映射。如果bss段长度不为0,执行⑸把bss段的内存区域清零。

STATIC UINT32 OsLoadUserInit(LosProcessCB *processCB)
{/*              userInitTextStart               -----* | user text |** | user data |                                initSize*              userInitBssStart  ---* | user bss  |                  initBssSize*              userInitEnd       ---           -----*/errno_t errRet;INT32 ret;
⑴  CHAR *userInitTextStart = (CHAR *)&__user_init_entry;CHAR *userInitBssStart = (CHAR *)&__user_init_bss;CHAR *userInitEnd = (CHAR *)&__user_init_end;UINT32 initBssSize = userInitEnd - userInitBssStart;UINT32 initSize = userInitEnd - userInitTextStart;VOID *userBss = NULL;VOID *userText = NULL;⑵  if ((LOS_Align((UINTPTR)userInitTextStart, PAGE_SIZE) != (UINTPTR)userInitTextStart) ||(LOS_Align((UINTPTR)userInitEnd, PAGE_SIZE) != (UINTPTR)userInitEnd)) {return LOS_EINVAL;}if ((initSize == 0) || (initSize <= initBssSize)) {return LOS_EINVAL;}⑶  userText = LOS_PhysPagesAllocContiguous(initSize >> PAGE_SHIFT);if (userText == NULL) {return LOS_NOK;}errRet = memcpy_s(userText, initSize, (VOID *)&__user_init_load_addr, initSize - initBssSize);if (errRet != EOK) {PRINT_ERR("Load user init text, data and bss failed! err : %d\n", errRet);goto ERROR;}
⑷  ret = LOS_VaddrToPaddrMmap(processCB->vmSpace, (VADDR_T)(UINTPTR)userInitTextStart, LOS_PaddrQuery(userText),initSize, VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE |VM_MAP_REGION_FLAG_FIXED | VM_MAP_REGION_FLAG_PERM_EXECUTE |VM_MAP_REGION_FLAG_PERM_USER);if (ret < 0) {PRINT_ERR("Mmap user init text, data and bss failed! err : %d\n", ret);goto ERROR;}/* The User init boot segment may not actually exist */
⑸  if (initBssSize != 0) {userBss = (VOID *)((UINTPTR)userText + userInitBssStart - userInitTextStart);errRet = memset_s(userBss, initBssSize, 0, initBssSize);if (errRet != EOK) {PRINT_ERR("memset user init bss failed! err : %d\n", errRet);goto ERROR;}}return LOS_OK;ERROR:(VOID)LOS_PhysPagesFreeContiguous(userText, initSize >> PAGE_SHIFT);return LOS_NOK;
}

3.2 用户初始化栈函数OsUserInitStackAlloc

该函数需要2个参数,第一个参数为进程控制块,第二个参数为输出参数,用于获取用户任务栈的大小。⑴处用户任务栈大小对页进行对齐,然后申请内存区域,然后执行⑵设置内存区域类型,并社区内存区域标签为栈。然后设置输出参数为任务栈大小,并返回用户栈空间的开始地址。

STATIC VOID *OsUserInitStackAlloc(LosProcessCB *processCB, UINT32 *size)
{LosVmMapRegion *region = NULL;
⑴  UINT32 stackSize = ALIGN(OS_USER_TASK_STACK_SIZE, PAGE_SIZE);region = LOS_RegionAlloc(processCB->vmSpace, 0, stackSize,VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ |VM_MAP_REGION_FLAG_PERM_WRITE, 0);if (region == NULL) {return NULL;}⑵  LOS_SetRegionTypeAnon(region);region->regionFlags |= VM_MAP_REGION_FLAG_STACK;*size = stackSize;return (VOID *)(UINTPTR)region->range.base;
}

3.3 用户进程初始化开启函数OsUserInitProcessStart

用户进程初始化开启函数OsUserInitProcessStart用于创建线程,设置调度策略等。⑴处为用户态进程创建个线程,然后为进程设置优先级。⑵处设置进程状态为非初始化状态,然后执行⑶为任务设置调度策略和优先级。

STATIC UINT32 OsUserInitProcessStart(LosProcessCB *processCB, TSK_INIT_PARAM_S *param)
{UINT32 intSave;INT32 ret;⑴  UINT32 taskID = OsCreateUserTask(processCB->processID, param);if (taskID == OS_INVALID_VALUE) {return LOS_NOK;}ret = LOS_SetProcessPriority(processCB->processID, OS_PROCESS_USERINIT_PRIORITY);if (ret != LOS_OK) {PRINT_ERR("User init process set priority failed! ERROR:%d \n", ret);goto EXIT;}SCHEDULER_LOCK(intSave);
⑵  processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;SCHEDULER_UNLOCK(intSave);⑶  ret = LOS_SetTaskScheduler(taskID, LOS_SCHED_RR, OS_TASK_PRIORITY_LOWEST);if (ret != LOS_OK) {PRINT_ERR("User init process set scheduler failed! ERROR:%d \n", ret);goto EXIT;}return LOS_OK;EXIT:(VOID)LOS_TaskDelete(taskID);return ret;
}

3.4 用户态进程初始化函数OsUserInitProcess

用户态进程初始化函数OsUserInitProcess完成用户态进程的初始化。⑴处获取用户态根进程,然后调用函数创建用户态根进程,并调用函数OsLoadUserInit加载用户初始化数据。⑵处初始化用户栈,然后设置线程的初始化参数,⑶处完成用户态进程的创建。

LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
{UINT32 ret;UINT32 size;TSK_INIT_PARAM_S param = { 0 };VOID *stack = NULL;⑴  LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess);ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init");if (ret != LOS_OK) {return ret;}ret = OsLoadUserInit(processCB);if (ret != LOS_OK) {goto ERROR;}⑵  stack = OsUserInitStackAlloc(processCB, &size);if (stack == NULL) {PRINT_ERR("Alloc user init process user stack failed!\n");goto ERROR;}param.pfnTaskEntry = (TSK_ENTRY_FUNC)(CHAR *)&__user_init_entry;param.userParam.userSP = (UINTPTR)stack + size;param.userParam.userMapBase = (UINTPTR)stack;param.userParam.userMapSize = size;param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
⑶  ret = OsUserInitProcessStart(processCB, &param);if (ret != LOS_OK) {(VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);goto ERROR;}return LOS_OK;ERROR:OsDeInitPCB(processCB);return ret;
}

小结

本文介绍了进程管理的内核进程、用户态进程的初始化相关函数。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://qr21.cn/FV7h05

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

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

相关文章

Spring 内置BeanPostProcessor 的子子孙孙

Spring 框架已经实现了很多BeanPostProcessor的类&#xff0c;如下是关于BeanPostProcessor 的类图&#xff0c;图片过大&#xff0c;可以下载资源包看。 要能说清楚这些类&#xff0c;挺难&#xff0c;我也不知道怎么写&#xff0c;这几个类都分布在不同的包中&#xff0c;我感…

Spring系统学习 - Bean的作用域

bean作用域介绍 Spring框架提供了不同的作用域来管理Bean的生命周期和可见性&#xff0c;这对于控制不同类型的组件和处理并发请求尤其重要。 singleton&#xff08;默认&#xff09;&#xff1a; 每个Spring IoC容器只有一个bean实例。当容器创建bean后&#xff0c;它会被缓存…

C#聊天室①

聊天室服务器&#xff1a; 创建项目 桌面不需要使用控件 Program.cs internal class Program {static TcpListener server;[STAThread]static void Main(){Program p new Program(); p.start();}void start(){server new TcpListener(IPAddress.Parse(GetIP()), 33…

iText7——画发票PDF(完整)

显示描述&#xff1a; 1、每页显示必须带有发票头、“销售方和购买方信息” 2、明细填充为&#xff1a;当n≤8 行时&#xff0c;发票总高度140mm&#xff0c;每条发票明细行款高度4.375mm&#xff1b; 当8<n≤12行时&#xff0c;发票高度增加17.5mm&#xff0c;不换页&#…

【模拟-BM100 设计LRU缓存结构】

题目 BM100 设计LRU缓存结构 描述 设计LRU(最近最少使用)缓存结构&#xff0c;该结构在构造时确定大小&#xff0c;假设大小为 capacity &#xff0c;操作次数是 n &#xff0c;并有如下功能: Solution(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存get(key)&am…

【PyTorch 新手基础】Regularization -- 减轻过拟合 overfitting

Overfit 过拟合&#xff0c;效果如最右图所示 常见应对方案如下&#xff1a; 增大数据集入手&#xff1a;More data or data argumentation简化模型参数入手&#xff1a;Constraint model complexity (shallow model, regularization) or dropout dropout: torch.nn.Dropout(0…

搭建一个好玩的 RSS 订阅网站记录

全文相关链接 Github仓库创建链接Railway官网Supabase官网f-droid上的co.appreactor.news应用下载链接Railway账户使用量估算链接 全文相关代码 原文地址: https://blog.taoshuge.eu.org/p/270/ Dockerfile FROM docker.io/miniflux/miniflux:2.1.3环境变量 DATABASE_URL…

Java线程池参数和处理流程

线程池是一种管理和重用线程资源的机制&#xff0c;是利用池化思想设置和管理多线程的工具。线程池维护一定数量的线程&#xff0c;当有任务需要时&#xff0c;就从中选择一个的线程用来执行任务&#xff0c;当使用完成后该线程就会被重新放回线程池中&#xff0c;通过这样循环…

Apollo配置中心最佳实践

携程配置中心地址&#xff1a;GitCode - 全球开发者的开源社区,开源代码托管平台 1.1 Apollo配置中心介绍 Apollo&#xff08;阿波罗&#xff09;是开源配置管理中心&#xff0c;能够集中化管理应用不同环境、不同集群的配置&#xff0c;配置修改后能够实时推送到应用端…

ASM字节码插桩实现点击防抖

思路&#xff1a;在点击事件onclick的时候&#xff0c;将view的onclick在给定的时间给拦截掉。以前我们可能都是用一个util来拦截&#xff0c;这样在每个点击事件都得去判断&#xff0c;那么这里就用字节码插桩的形式来实现一下。 ASM的引入 dependencies {implementation gr…

QT day01

思维导图 QT编程 实现一个账号登录界面 代码&#xff1a; myweidget.h #ifndef MYWEIDGET_H #define MYWEIDGET_H#include <QWidget> #include <QIcon> //图标类 #include <QLineEdit> //行编辑器类 #include <QLabel> //标签类 #…

【Redis】安装和命令行客户端

https://www.bilibili.com/video/BV1cr4y1671t https://www.oz6.cn/articles/58 redis 非结构化有&#xff1a; 键值类型(Redis)文档类型(MongoDB)列类型(HBase)Graph:类型(Neo4j) 扩展性&#xff1a;水平即为分布式扩展 redis特征 键值&#xff08;key-value&#xff09;型…

【springBoot学习篇】springBoot集成mybatis

目录 第一步&#xff1a;新建spring项目的时候&#xff0c;需要勾选mybatis框架和jdbc连接数据库的包 第二步&#xff1a;在resource目录下面的配置文件当中添加以下的内容&#xff1a;配置数据源 第三步&#xff1a;配置实体类 第四步&#xff1a;添加一个对象的增删改查方…

上位机图像处理和嵌入式模块部署(h750 mcu和图像处理)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;h750和之前的103、407相比较&#xff0c;本身cpu频率比较高&#xff0c;flash大小一般&#xff0c;但是ram比较大&#x…

群辉其它方案远程访问(ZeroTier篇)

目录 1、注册ZeroTier 2、创建网络 3、下载安装客户端 (1)Windows (2)移动端 i.Android i.iOS (a)注册新ID (b)登陆苹果应用商店 iii.群辉NAS 4、客户端加入网络 (a)Windows (b)Android (c)群辉NAS 5、使用 群辉的远程访问,最标准的做法就是使用…

自动控制原理【期末复习】(二)

无人机上桨之后可以在调试架上先调试&#xff1a; 1.根轨迹的绘制 /// 前面针对的是时域分析&#xff0c;下面针对频域分析&#xff1a; 2.波特图 3.奈维斯特图绘制 1.奈氏稳定判据 2.对数稳定判据 3.相位裕度和幅值裕度

【全篇】Python从零基础到入门

文章目录 第一章 基础语法1.字面量2.注释3.变量4.数据类型5.数据类型转换6.标识符7.运算符8.字符串拓展1.字符串的三种定义方式2.字符串拼接&#xff08;不用&#xff09;3.字符串格式化&#xff08;了解&#xff09;4.格式化的精度控制5.字符串格式化2&#xff08;常用&#x…

跟《经济学人》学英文:2024年6月8日这期:Part 01

本文是对《经济学人》杂志2024.6.8这期的英文学习。 Narendra Modi looks likely to serve a third term as India’s prime minister, after his Bharatiya Janata Party and its allies won a slim majority. The ruling alliance won 293 seats, compared with the opposi…

【代码随想录】【算法训练营】【第36天】[452]用最少数量的箭引爆气球 [435]无重叠区间 [763]划分字母区间

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 36&#xff0c;周三&#xff0c;最难坚持的一天~ 题目详情 [452] 用最少数量的箭引爆气球 题目描述 452 用最少数量的箭引爆气球 解题思路 前提&#xff1a;区间可能重叠 思路&#xff1a;…

YOLO系列理论解读 v1 v2 v3

YOLO系列理论解读 YOLO v1&#xff08;You Only Look Once:Unified, Real-Time Object Detection&#xff09; YOLO v1实现步骤 将一幅图像分成SxS个网格(grid cell)&#xff0c;如果某个object的中心落在这个网格中&#xff0c;则这个网格就负责预测这个object。 通常情况…