鸿蒙轻内核A核源码分析系列四(2) 虚拟内存

本文我们来熟悉下OpenHarmony鸿蒙轻内核提供的虚拟内存(Virtual memory)管理模块。

本文中所涉及的源码,以OpenHarmony LiteOS-A内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板,则默认以hispark_taurus为例。

我们首先了解了虚拟内存管理的结构体、相关宏定义,接着会分析内核虚拟地址空间和用户进程虚拟地址空间如何初始化,然后分析虚拟内存区间常用操作包含查找、申请和释放等,最后分析动态内存堆的申请、释放接口的源代码,并简单介绍下内存区间预留接口源代码。

1、 虚拟内存管理相关的结构体

在文件kernel/base/include/los_vm_map.h中定义了进程地址空间结构体LosVmSpace,进程地址区间结构体LosVmMapRegion和进程地址区间范围结构体LosVmMapRange。每个用户态进程会创建自己的进程空间,内核态会创建2个进程空间,分别g_kVmSpaceg_vMallocSpace。从进程空间申请的虚拟内存块使用进程区间LosVmMapRegion来表示。每个进程空间维护一个红黑树来链接各个进程区间。

1.1 虚拟内存地址空间结构体LosVmSpace

typedef struct VmSpace {LOS_DL_LIST         node;           /**< 地址空间双向链表 */LosRbTree           regionRbTree;   /**< 地址区间的红黑树根节点 */LosMux              regionMux;      /**< 地址区间的红黑树的互斥锁 */VADDR_T             base;           /**< 地址空间开始地址 */UINT32              size;           /**< 地址空间大小 */VADDR_T             heapBase;       /**< 地址空间的堆开始地址heapBase */VADDR_T             heapNow;        /**< 地址空间的堆开始地址heapNow */LosVmMapRegion      *heap;          /**< 地址空间的地址区间 */VADDR_T             mapBase;        /**< 地址空间的映射区开始地址 */UINT32              mapSize;        /**< 地址空间的映射区大小 */LosArchMmu          archMmu;        /**< 地址空间的MMU结构体 */
#ifdef LOSCFG_DRIVERS_TZDRIVERVADDR_T             codeStart;      /**< 用户进程代码区开始地址 */VADDR_T             codeEnd;        /**< 用户进程代码区结束地址 */
#endif
} LosVmSpace;

1.2 虚拟内存地址区间LosVmMapRegion

typedef struct VmMapRange {VADDR_T             base;           /**< 虚拟内存地址区间开始地址 */UINT32              size;           /**< 虚拟内存地址区间大小 */
} LosVmMapRange;
......
struct VmMapRegion;
typedef struct VmMapRegion LosVmMapRegion;
......
struct VmMapRegion {LosRbNode           rbNode;         /**<  地址区间红黑树节点 */LosVmSpace          *space;         /**<  地址区间所在的地址空间 */LOS_DL_LIST         node;           /**<  地址区间双向链表 */LosVmMapRange       range;          /**<  地址区间地址范围 */VM_OFFSET_T         pgOff;          /**<  地址区间页偏移 */UINT32              regionFlags;    /**<  地址区间标记: cow, user_wired */UINT32              shmid;          /**<  共享地址区间编号 */UINT8               forkFlags;      /**<  地址区间fork标记: COPY, ZERO, */UINT8               regionType;     /**<  地址区间类型: ANON, FILE, DEV */union {struct VmRegionFile {unsigned int fileMagic;struct file *file;const LosVmFileOps *vmFOps;} rf;struct VmRegionAnon {LOS_DL_LIST  node;          /**< 地址区间类型的双向链表 */} ra;struct VmRegionDev {LOS_DL_LIST  node;          /**< 地址区间类型的双向链表 */const LosVmFileOps *vmFOps;} rd;} unTypeData;
};

2、 虚拟内存相关的宏定义

文件kernel/base/include/los_vm_common.hkernel/base/include/los_vm_zone.h定义了虚拟内存相关的宏。对于32位系统,虚拟进程空间大小为4GiB,OpenHarmony鸿蒙轻内核当前支持32位系统。⑴和⑵定义了用户进程虚拟地址空间的开始地址和大小,⑶是用户虚拟进程空间的结束地址,接着定义的是用户虚拟进程空间的堆区、映射区的开始地址和大小。

/* user address space, defaults to below kernel space with a 16MB guard gap on either side */#ifndef USER_ASPACE_BASE
⑴  #define USER_ASPACE_BASE            ((vaddr_t)0x01000000UL)#endif#ifndef USER_ASPACE_SIZE
⑵  #define USER_ASPACE_SIZE            ((vaddr_t)KERNEL_ASPACE_BASE - USER_ASPACE_BASE - 0x01000000UL)#endif⑶  #define USER_ASPACE_TOP_MAX         ((vaddr_t)(USER_ASPACE_BASE + USER_ASPACE_SIZE))#define USER_HEAP_BASE              ((vaddr_t)(USER_ASPACE_TOP_MAX >> 2))#define USER_MAP_BASE               ((vaddr_t)(USER_ASPACE_TOP_MAX >> 1))#define USER_MAP_SIZE               ((vaddr_t)(USER_ASPACE_SIZE >> 3))

内核虚拟进程空间的宏定义如下,⑴处定义内核进程地址空间开始地址和大小,⑵处定义内核非缓存虚拟地址空间开始地址和大小,⑶处定义虚拟动态分配地址空间开始地址和大小,⑷处定义外设开始地址和大小,⑸处定义外设缓存区开始地址和大小,⑹处定义外设非缓存区开始地址和大小。

    #ifdef LOSCFG_KERNEL_MMU#ifdef LOSCFG_TEE_ENABLE#define KERNEL_VADDR_BASE       0x41000000#else#define KERNEL_VADDR_BASE       0x40000000#endif#else#define KERNEL_VADDR_BASE       DDR_MEM_ADDR#endif#define KERNEL_VADDR_SIZE       DDR_MEM_SIZE#define SYS_MEM_BASE            DDR_MEM_ADDR#define SYS_MEM_END             (SYS_MEM_BASE + SYS_MEM_SIZE_DEFAULT)#define _U32_C(X)  X##U#define U32_C(X)   _U32_C(X)#define KERNEL_VMM_BASE         U32_C(KERNEL_VADDR_BASE)#define KERNEL_VMM_SIZE         U32_C(KERNEL_VADDR_SIZE)⑴  #define KERNEL_ASPACE_BASE      KERNEL_VMM_BASE#define KERNEL_ASPACE_SIZE      KERNEL_VMM_SIZE/* Uncached vmm aspace */
⑵  #define UNCACHED_VMM_BASE       (KERNEL_VMM_BASE + KERNEL_VMM_SIZE)#define UNCACHED_VMM_SIZE       DDR_MEM_SIZE⑶  #define VMALLOC_START           (UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)#define VMALLOC_SIZE            0x08000000#ifdef LOSCFG_KERNEL_MMU
⑷  #define PERIPH_DEVICE_BASE      (VMALLOC_START + VMALLOC_SIZE)#define PERIPH_DEVICE_SIZE      U32_C(PERIPH_PMM_SIZE)
⑸  #define PERIPH_CACHED_BASE      (PERIPH_DEVICE_BASE + PERIPH_DEVICE_SIZE)#define PERIPH_CACHED_SIZE      U32_C(PERIPH_PMM_SIZE)
⑹  #define PERIPH_UNCACHED_BASE    (PERIPH_CACHED_BASE + PERIPH_CACHED_SIZE)#define PERIPH_UNCACHED_SIZE    U32_C(PERIPH_PMM_SIZE)#else#define PERIPH_DEVICE_BASE      PERIPH_PMM_BASE#define PERIPH_DEVICE_SIZE      U32_C(PERIPH_PMM_SIZE)#define PERIPH_CACHED_BASE      PERIPH_PMM_BASE#define PERIPH_CACHED_SIZE      U32_C(PERIPH_PMM_SIZE)#define PERIPH_UNCACHED_BASE    PERIPH_PMM_BASE#define PERIPH_UNCACHED_SIZE    U32_C(PERIPH_PMM_SIZE)#endif

虚拟地址空间分布示意图如下:

3、进程地址空间初始化

虚拟进程空间分用户虚拟进程空间和内核虚拟进程空间,每个用户进程都会创建属于自己的进程空间。内核会初始化2个进程空间。下文详细介绍。

3.1 内核虚拟地址空间初始化

3.1.1 函数OsKSpaceInit

函数OsKSpaceInit()初始化内核进程虚拟地址空间,⑴处的函数初始化虚拟空间链表互斥锁g_vmSpaceListMux,在操作内核进程空间时需要持有该互斥锁。⑵处开始的函数2个函数OsKernVmSpaceInitOsVMallocSpaceInit分别初始化内核进程虚拟空间g_kVmSpace和内核动态分配进程空间g_vMallocSpace。传入的第2个参数由函数OsGFirstTableGet()获取,即g_firstPageTable,这是内核的2个进程空间使用的一级页表基地址,大小为0x4000字节,后文在设置转化表基地址MMU virtTtb时会使用。下文会详细分析这2个函数。

VOID OsKSpaceInit(VOID)
{
⑴  OsVmMapInit();
⑵  OsKernVmSpaceInit(&g_kVmSpace, OsGFirstTableGet());OsVMallocSpaceInit(&g_vMallocSpace, OsGFirstTableGet());
}

3.1.2 函数OsKernVmSpaceInit

函数OsKernVmSpaceInit()初始化内核进程虚拟地址空间,⑴处设置地址空间的开始地址和大小,⑵处设置地址空间映射区的开始地址和大小,对于内核虚拟地址空间g_kVmSpace,这2个开始地址和大小是一样的。⑶处调用通用的地址空间初始化函数,后文分析此函数。

BOOL OsKernVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
{
⑴  vmSpace->base = KERNEL_ASPACE_BASE;vmSpace->size = KERNEL_ASPACE_SIZE;
⑵  vmSpace->mapBase = KERNEL_VMM_BASE;vmSpace->mapSize = KERNEL_VMM_SIZE;
#ifdef LOSCFG_DRIVERS_TZDRIVERvmSpace->codeStart = 0;vmSpace->codeEnd = 0;
#endif
⑶   return OsVmSpaceInitCommon(vmSpace, virtTtb);
}

3.1.3 函数OsVMallocSpaceInit

函数OsVMallocSpaceInit()初始化内核堆虚拟空间,设置的虚拟地址空间和映射区地址空间的开始地址和大小也是一样的,代码和函数OsKernVmSpaceInit()类似,不再赘述。

BOOL OsVMallocSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
{vmSpace->base = VMALLOC_START;vmSpace->size = VMALLOC_SIZE;vmSpace->mapBase = VMALLOC_START;vmSpace->mapSize = VMALLOC_SIZE;
#ifdef LOSCFG_DRIVERS_TZDRIVERvmSpace->codeStart = 0;vmSpace->codeEnd = 0;
#endifreturn OsVmSpaceInitCommon(vmSpace, virtTtb);
}

3.2 用户进程虚拟地址空间初始化

3.2.1 函数OsCreateUserVmSpace

在创建进程时,会调用函数OsCreateUserVmSpace()创建用户进程的虚拟地址空间。⑴为虚拟地址空间结构体申请内存。⑵申请一个内存页,并调用memset_s()初始化为0,这个内存页虚拟地址会作为页表转换基地址TTB(translation table base,ttb),虚实映射的页表会保存在这个内存区域。在虚实映射章节,会讲述为什么申请4KiB大小内存。⑶处调用函数OsUserVmSpaceInit初始化用户进程虚拟地址空间。⑷处获取虚拟地址对应的物理页结构体地址。如果初始化失败,则释放申请的内存。⑸处把物理页加入虚拟空间中的MMU的页表链表中,这个链表维护该进程空间映射的内存页。

LosVmSpace *OsCreateUserVmSpace(VOID)
{BOOL retVal = FALSE;⑴   LosVmSpace *space = LOS_MemAlloc(m_aucSysMem0, sizeof(LosVmSpace));if (space == NULL) {return NULL;}⑵  VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);if (ttb == NULL) {(VOID)LOS_MemFree(m_aucSysMem0, space);return NULL;}(VOID)memset_s(ttb, PAGE_SIZE, 0, PAGE_SIZE);
⑶  retVal = OsUserVmSpaceInit(space, ttb);
⑷  LosVmPage *vmPage = OsVmVaddrToPage(ttb);if ((retVal == FALSE) || (vmPage == NULL)) {(VOID)LOS_MemFree(m_aucSysMem0, space);LOS_PhysPagesFreeContiguous(ttb, 1);return NULL;}
⑸   LOS_ListAdd(&space->archMmu.ptList, &(vmPage->node));return space;
}

3.2.2 函数OsUserVmSpaceInit

函数OsUserVmSpaceInit初始化用户进程虚拟地址空间,⑴处设置虚拟地址空间的开始地址和大小。⑵处设置虚拟空间的映射区的开始地址和大小,开始地址在虚拟空间开始地址的1/2处,大小为用户虚拟空间大小的1/8。⑶处设置虚拟空间的堆区,开始地址为虚拟空间开始地址的1/4处。

BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
{
⑴  vmSpace->base = USER_ASPACE_BASE;vmSpace->size = USER_ASPACE_SIZE;
⑵  vmSpace->mapBase = USER_MAP_BASE;vmSpace->mapSize = USER_MAP_SIZE;
⑶  vmSpace->heapBase = USER_HEAP_BASE;vmSpace->heapNow = USER_HEAP_BASE;vmSpace->heap = NULL;
#ifdef LOSCFG_DRIVERS_TZDRIVERvmSpace->codeStart = 0;vmSpace->codeEnd = 0;
#endifreturn OsVmSpaceInitCommon(vmSpace, virtTtb);
}

3.3 虚拟地址空间初始化的通用函数

3.3.1 函数OsVmSpaceInitCommon

函数OsVmSpaceInitCommon用于进程虚拟地址空间的通用部分的初始化,⑴处初始化地址空间的红黑树根节点。⑵处初始化地址空间的地址区间操作互斥锁。⑶处把新创建的地址空间挂在虚拟地址空间双向链表g_vmSpaceList上。⑷处继续调用函数OsArchMmuInit()完成地址空间MMU部分的初始化。

STATIC BOOL OsVmSpaceInitCommon(LosVmSpace *vmSpace, VADDR_T *virtTtb)
{
⑴  LOS_RbInitTree(&vmSpace->regionRbTree, OsRegionRbCmpKeyFn, OsRegionRbFreeFn, OsRegionRbGetKeyFn);⑵  status_t retval = LOS_MuxInit(&vmSpace->regionMux, NULL);if (retval != LOS_OK) {VM_ERR("Create mutex for vm space failed, status: %d", retval);return FALSE;}(VOID)LOS_MuxAcquire(&g_vmSpaceListMux);
⑶  LOS_ListAdd(&g_vmSpaceList, &vmSpace->node);(VOID)LOS_MuxRelease(&g_vmSpaceListMux);⑷   return OsArchMmuInit(&vmSpace->archMmu, virtTtb);
}

3.3.2 函数OsArchMmuInit

函数OsArchMmuInit()用于初始化虚拟地址空间的MMU,MMU在后续系列会详细分析,此处快速了解一下即可。⑴处获取地址空间编号,如果获取失败则返回FALSE。⑵初始化MMU互斥锁,如果初始化失败则返回FALSE。⑶处初始化内存页双向链表。⑷处设置MMU的TTB虚拟地址。⑸处设置MMU的TTB物理地址,TTB虚拟地址基于内核虚拟地址空间开始地址的偏移(UINTPTR)virtTtb - KERNEL_ASPACE_BASE加上物理地址就等于TTB物理地址。

BOOL OsArchMmuInit(LosArchMmu *archMmu, VADDR_T *virtTtb)
{
#ifdef LOSCFG_KERNEL_VM
⑴   if (OsAllocAsid(&archMmu->asid) != LOS_OK) {VM_ERR("alloc arch mmu asid failed");return FALSE;}
#endif⑵   status_t retval = LOS_MuxInit(&archMmu->mtx, NULL);if (retval != LOS_OK) {VM_ERR("Create mutex for arch mmu failed, status: %d", retval);return FALSE;}⑶  LOS_ListInit(&archMmu->ptList);
⑷  archMmu->virtTtb = virtTtb;
⑸  archMmu->physTtb = (VADDR_T)(UINTPTR)virtTtb - KERNEL_ASPACE_BASE + SYS_MEM_BASE;return TRUE;
}

4、虚拟地址区间常用操作

虚拟地址区间操作分为查找、申请、释放等操作。

4.1 函数LOS_RegionFind

⑴处的函数LOS_RegionFind用于在进程虚拟地址空间内查找并返回指定虚拟地址对应的虚拟地址区间,两个传入参数分别是虚拟地址空间和虚拟内存地址。该函数有个兄弟函数LOS_RegionRangeFind(),见⑶处代码,可以用于在进程空间内查找并返回指定地址范围对应的虚拟地址区间,三个传入参数分别指定指定进程空间、虚拟内存开始地址和地址长度(长度单位字节)。这2个函数都调用函数OsFindRegion()实现地址区间的查找,⑵处的第3个参数为1的原因是地址区间是左闭右开区间,区间的结束地址会减1。下文会分析该函数的代码。

⑴   LosVmMapRegion *LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr){LosVmMapRegion *region = NULL;(VOID)LOS_MuxAcquire(&vmSpace->regionMux);
⑵      region = OsFindRegion(&vmSpace->regionRbTree, addr, 1);(VOID)LOS_MuxRelease(&vmSpace->regionMux);return region;}
⑶  LosVmMapRegion *LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len){LosVmMapRegion *region = NULL;(VOID)LOS_MuxAcquire(&vmSpace->regionMux);region = OsFindRegion(&vmSpace->regionRbTree, addr, len);(VOID)LOS_MuxRelease(&vmSpace->regionMux);return region;}

如果大家想更加深入的学习 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/pingmian/28684.shtml

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

相关文章

Aigtek高压放大器在柔性爬行机器人驱动性能研究中的应用

实验名称&#xff1a;柔性爬行机器人的材料测试 研究方向&#xff1a;介电弹性体的最小能量结构是一种利用DE材料的电致变形与柔性框架形变相结合设计的新型柔性驱动器&#xff0c;所谓最小能量是指驱动器在平衡状态时整个系统的能量最小&#xff0c;当系统在外界的电压刺激下就…

10.Docker Compose容器编排

文章目录 Compose简介安装和卸载步骤核心概念compose文件两要素 使用步骤Compose常用命令微服务测试本地编码打包编写Dockerfile文件构建镜像 不使用Compose调试使用Compose调试WordPress测试验证增量更新 Compose简介 ​ docker建议我们每一个容器中只运行一个服务,因为docke…

Memcached深度解析:打造闪电般的数据存储

Memcached是一个高性能的分布式内存对象缓存系统&#xff0c;通过在内存中缓存数据和对象来减少访问数据库的次数&#xff0c;从而加速动态数据库驱动的网站。本文将全面介绍Memcached的基本概念、使用方法、主要作用以及注意事项。 一、Memcached简介 1. Memcached的起源 Me…

开源复刻apple 数学笔记;纯C++实现了ChatGLM系列模型;腾讯混元文生图模型发布新版本并开源训练代码

✨ 1: AI Math Notes AI Math Notes 是一个交互式绘图应用&#xff0c;可绘制并计算数学方程。 AI Math Notes 受到Apple在WWDC 2024上的“Math Notes”演启发&#xff0c;开发的一个互动式绘图应用程序&#xff0c;用户可以在画布上绘制数学方程。一旦方程被绘制完成&#x…

Win11升级24H2出现绿屏怎么办?这些方法帮你解决!

在Win11电脑操作中&#xff0c;用户为了体验24H2版本推出的新功能&#xff0c;所以要把系统版本升级为24H2版本。但升级过程中电脑却出现了绿屏问题&#xff0c;不清楚要怎么操作才能解决绿屏的问题&#xff1f;接下来小编给大家分享几种简单有效的解决方法&#xff0c;让大家能…

CSRF、XSS、盗链攻击解释

CSRF&#xff08;Cross-Site Request Forgery&#xff0c;跨站请求伪造&#xff09; CSRF是什么 CSRF 是一种攻击方式&#xff0c;攻击者通过利用用户在已认证的应用程序中的身份&#xff0c;伪造用户的请求来执行未经授权的操作。 这种攻击可以导致用户在不知情的情况下完成…

氧化铈稳定氧化锆(Ce-TZP)性能优成本低 市场发展潜力较大

氧化铈稳定氧化锆&#xff08;Ce-TZP&#xff09;性能优成本低 市场发展潜力较大 CeO2稳定ZrO2&#xff0c;氧化铈稳定氧化锆&#xff0c;英文缩写Ce-TZP&#xff0c;一种陶瓷材料&#xff0c;是以氧化锆为基体&#xff0c;以氧化铈为稳定剂&#xff0c;制造而成的增韧陶瓷。 氧…

芯片封测从入门到精通

文章目录 &#x1f4d1;前言一、作者简介二、书籍亮点三、内容简介四、适读人群 &#x1f4d1;前言 在科技日新月异的今天&#xff0c;芯片作为现代电子设备的核心部件&#xff0c;其性能与可靠性直接决定了整个产品的竞争力。而芯片封测&#xff0c;作为确保芯片性能与可靠性…

Aspice介绍——测试流程

文章目录 ASPICE简介一、V字模型的示意二、测试领域2.1 SWE.6&#xff1a;软件合格性测试过程目的过程成果基本实践&#xff08;BP&#xff09; 2.2 SYS.4:系统集成和集成测试过程目的过程成果基本实践&#xff08;BP&#xff09; 2.3 SYS.5&#xff1a;系统合格性测试过程目的…

【Java】已解决java.lang.NullPointerException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.NullPointerException异常 一、问题背景 在Java编程中&#xff0c;java.lang.NullPointerException&#xff08;空指针异常&#xff09;是一种常见的运行时异常。当应…

一些个人电脑用的小工具软件

1 个人电脑信息管理 如下&#xff1b; 整理自己的电脑信息&#xff1b;录入&#xff0c;保存&#xff0c;查询&#xff1b;添加和更新界面如下&#xff0c; 每次添加、更新之后重新点一下菜单的浏览&#xff1b; 下载&#xff0c; https://download.csdn.net/download/bcb…

SpringBoot+Vue小区物业管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.用户登录代码2.查询小区信息代码3.保存缴费信息代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootVue框架开发的小区物业管理系统。首先&#xf…

深入探索 Rust 的 clap 库:命令行解析的艺术

版本声明 Rust: 1.76clap: 4.5.1clap_complete 4.5.1rpassword: 7.3.1 结论先行 本文将从 CLI&#xff08;Command Line Interface&#xff09;命令行工具的概述讲起&#xff0c;介绍一个优秀的命令行工具应该具备的功能和特性。然后介绍 Rust 中一个非常优秀的命令行解析工…

《Windows API每日一练》4.3 点和线的绘制

理论上&#xff0c;所有的图形设备驱动程序所需要的就是SetPixel函数和GetPixel函数。其余的一切都可以使用在GDI模块中实现的更高层的例程来处理。例如&#xff0c;画一条线&#xff0c;GDI可以不停地调整x和y坐标&#xff0c;然后连续调用多次SetPixel函数来实现。 事实上&a…

2024 年最新 windows 操作系统部署安装 redis 数据库详细教程(更新中)

Redis 数据库概述 Redis 是一个开源的&#xff0c;内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中介。Redis&#xff08;Remote Dictionary Server &#xff09;&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基…

数据通信与网络(二)

计算机网络的性能指标 包括速率、带宽、吞吐量、时延、时延带宽积和利用率。 还有一些非性能指标&#xff1a;如费用、质量、标准化、可靠性、可扩展性、可升级性和可维性。 一、速率 指计算机网络中的主机在信道上单位时间内传送数据量&#xff0c;又称数据率(data rate)或…

每日AI资讯-20240616

1. AI漫画角色一致性大突破 由中山大学和联想团队联合提出AutoStudio&#xff0c;它是一个无需训练的多智能体协同框架。AutoStudio采用基于大语言模型的三个智能体来处理交互&#xff0c;并使用基于扩散模型的Drawer生成高质量图像。实验中&#xff0c;AutoStudio无论是在定量…

腾讯地图避坑-获取地图点击点的经纬度

map.on(click,(evt)>{console.log("evt",evt)let lat evt.latLng.getLat();//lat 获取let lng evt.latLng.getLng();//lng 获取console.log("evt.latLng-有效方式",evt.latLng)console.log("evt[latlng]-无效方式",evt[latlng])})

PiDiNet推理手顺

GitHub链接 https://github.com/hellozhuo/pidinet 运行环境 Pyhton 3.8 filelock3.14.0 fsspec2024.5.0 imageio2.34.1 intel-openmp2021.4.0 Jinja23.1.4 lazy_loader0.4 MarkupSafe2.1.5 mkl2021.4.0 mpmath1.3.0 networkx3.1 numpy1.24.4 open…

小程序外卖开发中的关键技术与实现方法

小程序外卖服务凭借其便捷性和灵活性&#xff0c;正成为现代餐饮行业的重要组成部分。开发一个功能完善的小程序外卖系统&#xff0c;需要掌握一系列关键技术和实现方法。本文将介绍小程序外卖开发中的核心技术&#xff0c;并提供具体的代码示例&#xff0c;帮助开发者理解和实…