鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式

运行机制

共享好端端的一词,近些年被玩坏了,共享单车,共享充电宝,共享办公室,共享雨伞… 甚至还有共享女朋友,真是人有多大胆,共享有多大产。但凡事太尽就容易恶心到人,自己也一度被 共享内存 恶心到了,一直不想碰它,拖到了现在才写。

共享内存的原理简单,目的是为了进程间通讯,方法是通过映射到同一块物理内存。它是一种稀缺资源由内核按资源池方式管理,数量有限,默认是 192个,用资源ID唯一标识,用户进程需要时通过系统调用向内核申请共享内存大小,管理器从资源池中分配一个可用资源ID,并向物理内存申请对应的物理页框。

如何使用共享内存就涉及到了内存模块最重要的概念 映射,不清楚的可以翻看系列相关篇。有共享需求的进程在各自的进程空间中划出一个线性区映射到共享内存段,那如何找到这个共享内存段呢 ? 由系统调用提供操作接口,简单说是先通过参数key创建共享资源ID(shmid),再由shmid来连接/删除/控制 共享内存。详见本篇末尾的4个系统调用 Shm***

如何实现?

这是笔者看完内核共享内存模块画出来的图,尽量用一张图表达一个模块的内容,因为百文是在给源码注释的过程中产生的,所以会画出这种比较怪异的图,有代码,也有模型,姑且称之为 代码模型图:

图分 管理 和 映射使用 两部分解读。 为了精简,代码展示只留下骨干,删除了判断,检查的代码。

管理部分
  • 初始化共享内存,共享内存是以资源池的方式管理的,上来就为全局变量g_shmSegs向内核堆空间申请了g_shmInfo.shmmnistruct shmIDSource
    #define SHM_MNI 192 //共享内存总数 默认192// 共享内存模块设置信息struct shminfo {unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];};STATIC struct shminfo g_shmInfo = { //描述共享内存范围的全局变量.shmmax = SHM_MAX,//共享内存单个上限 4096页 即 16M.shmmin = SHM_MIN,//共享内存单个下限 1页 即:4K.shmmni = SHM_MNI,//共享内存总数 默认192 .shmseg = SHM_SEG,//每个用户进程可以使用的最多的共享内存段的数目 128.shmall = SHM_ALL,//系统范围内共享内存的总页数,4096页 };//共享内存初始化UINT32 ShmInit(VOID){// ..ret = LOS_MuxInit(&g_sysvShmMux, NULL);//初始化互斥g_shmSegs = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(struct shmIDSource) * g_shmInfo.shmmni);//分配shm段数组(VOID)memset_s(g_shmSegs, (sizeof(struct shmIDSource) * g_shmInfo.shmmni),0, (sizeof(struct shmIDSource) * g_shmInfo.shmmni));//数组清零for (i = 0; i < g_shmInfo.shmmni; i++) {g_shmSegs[i].status = SHM_SEG_FREE;//节点初始状态为空闲g_shmSegs[i].ds.shm_perm.seq = i + 1;//struct ipc_perm shm_perm;系统为每一个IPC对象保存一个ipc_perm结构体,结构说明了IPC对象的权限和所有者LOS_ListInit(&g_shmSegs[i].node);//初始化节点}g_shmUsedPageCount = 0;return LOS_OK;}
  • 系列篇多次提过,每个功能模块都至少有一个核心结构体来支撑模块的运行,进程是PCB,任务是TCB,而共享内存就是shmIDSource
    struct shmIDSource {//共享内存描述符struct shmid_ds ds; //是内核为每一个共享内存段维护的数据结构UINT32 status;	//状态 SHM_SEG_FREE ...LOS_DL_LIST node; //节点,挂VmPage#ifdef LOSCFG_SHELLCHAR ownerName[OS_PCB_NAME_LEN];#endif};

首先shmid_ds是真正描述共享内存信息的结构体,记录了本次共享内存由谁创建,大小,用户/组,访问时间等等。

    //每个共享内存段在内核中维护着一个内部结构shmid_dsstruct shmid_ds {struct ipc_perm shm_perm;///< 操作许可,里面包含共享内存的用户ID、组ID等信息size_t shm_segsz;	///< 共享内存段的大小,单位为字节time_t shm_atime;	///< 最后一个进程访问共享内存的时间	time_t shm_dtime; 	///< 最后一个进程离开共享内存的时间time_t shm_ctime; 	///< 创建时间pid_t shm_cpid;		///< 创建共享内存的进程IDpid_t shm_lpid;		///< 最后操作共享内存的进程IDunsigned long shm_nattch;	///< 当前使用该共享内存段的进程数量unsigned long __pad1;	//保留扩展用unsigned long __pad2;};//内核为每一个IPC对象保存一个ipc_perm结构体,该结构说明了IPC对象的权限和所有者struct ipc_perm {key_t __ipc_perm_key;	//调用shmget()时给出的关键字uid_t uid;				//共享内存所有者的有效用户IDgid_t gid;				//共享内存所有者所属组的有效组IDuid_t cuid;				//共享内存创建 者的有效用户IDgid_t cgid;				//共享内存创建者所属组的有效组IDmode_t mode;			//权限 + SHM_DEST / SHM_LOCKED /SHM_HUGETLB 标志位int __ipc_perm_seq;		//序列号long __pad1;			//保留扩展用long __pad2;};  

status 表示这段共享内存的状态,因为是资源池的方式,只有SHM_SEG_FREE的状态才可供分配,进程池和任务池也是这种管理方式。

      #define SHM_SEG_FREE    0x2000	//空闲未使用#define SHM_SEG_USED    0x4000	//已使用#define SHM_SEG_REMOVE  0x8000	//删除

node双向链表上挂的是一个个的物理页框VmPage,这是核心属性,数据将被存在这一个个物理页框中。ShmAllocSeg为具体的分配函数

    STATIC INT32 ShmAllocSeg(key_t key, size_t size, INT32 shmflg){// ... count = LOS_PhysPagesAlloc(size >> PAGE_SHIFT, &seg->node);//分配共享页面,函数内部把node都挂好了.if (count != (size >> PAGE_SHIFT)) {//当未分配到足够的内存时,处理方式是:不稀罕给那么点,舍弃!(VOID)LOS_PhysPagesFree(&seg->node);//释放节点上的物理页框seg->status = SHM_SEG_FREE;//共享段变回空闲状态return -ENOMEM;}ShmSetSharedFlag(seg);//将node的每个页面设置为共享页g_shmUsedPageCount += size >> PAGE_SHIFT;seg->status |= SHM_SEG_USED;	//共享段贴上已在使用的标签seg->ds.shm_perm.mode = (UINT32)shmflg & ACCESSPERMS;seg->ds.shm_perm.key = key;//保存参数key,如此 key 和 共享ID绑定在一块seg->ds.shm_segsz = size;	//共享段的大小seg->ds.shm_perm.cuid = LOS_GetUserID();	//设置用户IDseg->ds.shm_perm.uid = LOS_GetUserID();		//设置用户IDseg->ds.shm_perm.cgid = LOS_GetGroupID();	//设置组IDseg->ds.shm_perm.gid = LOS_GetGroupID();	//设置组IDseg->ds.shm_lpid = 0; //最后一个操作的进程seg->ds.shm_nattch = 0;	//绑定进程的数量					seg->ds.shm_cpid = LOS_GetCurrProcessID();	//获取进程IDseg->ds.shm_atime = 0;	//访问时间seg->ds.shm_dtime = 0;	//detach 分离时间 共享内存使用完之后,需要将它从进程地址空间中分离出来;将共享内存分离并不是删除它,只是使该共享内存对当前的进程不再可用seg->ds.shm_ctime = time(NULL);//创建时间#ifdef LOSCFG_SHELL(VOID)memcpy_s(seg->ownerName, OS_PCB_NAME_LEN, OsCurrProcessGet()->processName, OS_PCB_NAME_LEN);#endifreturn segNum;}
映射使用部分
  • 第一步: 创建共享内存 要实现共享内存,首先得创建一个内存段用于共享,干这事的是ShmGet
    /*!* @brief ShmGet	*	得到一个共享内存标识符或创建一个共享内存对象* @param key	建立新共享内存对象 标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案。为此,每个IPC对象都与一个键(key)相关联,这个键作为该对象的外部名,无论何时创建IPC结构(通过msgget、semget、shmget创建),都应给IPC指定一个键, key_t由ftok创建,ftok当然在本工程里找不到,所以要写这么多.* @param shmflg	IPC_CREAT IPC_EXCLIPC_CREAT:	在创建新的IPC时,如果key参数是IPC_PRIVATE或者和当前某种类型的IPC结构无关,则需要指明flag参数的IPC_CREAT标志位,则用来创建一个新的IPC结构。(如果IPC结构已存在,并且指定了IPC_CREAT,则IPC_CREAT什么都不做,函数也不出错)IPC_EXCL:	此参数一般与IPC_CREAT配合使用来创建一个新的IPC结构。如果创建的IPC结构已存在函数就出错返回,返回EEXIST(这与open函数指定O_CREAT和O_EXCL标志原理相同)* @param size	新建的共享内存大小,以字节为单位* @return	** @see*/INT32 ShmGet(key_t key, size_t size, INT32 shmflg){SYSV_SHM_LOCK();if (key == IPC_PRIVATE) {ret = ShmAllocSeg(key, size, shmflg);} else {ret = ShmFindSegByKey(key);//通过key查找资源IDret = ShmAllocSeg(key, size, shmflg);//分配一个共享内存}SYSV_SHM_UNLOCK();return ret;}
  • 第二步: 进程线性区绑定共享内存 shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。,ShmAt的第一个参数其实是ShmGet成功时的返回值 ,ShmatVmmAlloc负责分配一个可用的线性区并和共享内存映射好
    /*!* @brief ShmAt	* 用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。* @param shm_flg 是一组标志位,通常为0。* @param shmaddr 指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。* @param shmid	是shmget()函数返回的共享内存标识符* @return	* 如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值加1shmid 就是个索引,就跟进程和线程的ID一样 g_shmSegs[shmid] shmid > 192个* @see*/VOID *ShmAt(INT32 shmid, const VOID *shmaddr, INT32 shmflg){struct shmIDSource *seg = NULL;LosVmMapRegion *r = NULL;ret = ShmatParamCheck(shmaddr, shmflg);//参数检查SYSV_SHM_LOCK();seg = ShmFindSeg(shmid);//找到段ret = ShmPermCheck(seg, acc_mode);seg->ds.shm_nattch++;//ds上记录有一个进程绑定上来r = ShmatVmmAlloc(seg, shmaddr, shmflg, prot);//在当前进程空间分配一个线性区并映射到共享内存r->shmid = shmid;//把ID给线性区的shmidr->regionFlags |= VM_MAP_REGION_FLAG_SHM;//这是一个共享线性区seg->ds.shm_atime = time(NULL);//访问时间seg->ds.shm_lpid = LOS_GetCurrProcessID();//进程IDSYSV_SHM_UNLOCK();return (VOID *)(UINTPTR)r->range.base;}
  • 第三步: 控制/使用 共享内存,这才是目的,前面的都是前戏
    /*!* @brief ShmCtl	* 此函数可以对shmid指定的共享存储进行多种操作(删除、取信息、加锁、解锁等)* @param buf	是一个结构指针,它指向共享内存模式和访问权限的结构。* @param cmd	command是要采取的操作,它可以取下面的三个值 :IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值IPC_RMID:删除共享内存段* @param shmid	是shmget()函数返回的共享内存标识符* @return	** @see*/INT32 ShmCtl(INT32 shmid, INT32 cmd, struct shmid_ds *buf){SYSV_SHM_LOCK();switch (cmd) {case IPC_STAT:case SHM_STAT://取段结构ret = LOS_ArchCopyToUser(buf, &seg->ds, sizeof(struct shmid_ds));//把内核空间的共享页数据拷贝到用户空间if (cmd == SHM_STAT) {ret = (unsigned int)((unsigned int)seg->ds.shm_perm.seq << 16) | (unsigned int)((unsigned int)shmid & 0xffff); /* 16: use the seq as the upper 16 bits */}break;case IPC_SET://重置共享段ret = ShmPermCheck(seg, SHM_M);//从用户空间拷贝数据到内核空间ret = LOS_ArchCopyFromUser(&shm_perm, &buf->shm_perm, sizeof(struct ipc_perm));seg->ds.shm_perm.uid = shm_perm.uid;seg->ds.shm_perm.gid = shm_perm.gid;seg->ds.shm_perm.mode = (seg->ds.shm_perm.mode & ~ACCESSPERMS) |(shm_perm.mode & ACCESSPERMS);//可访问seg->ds.shm_ctime = time(NULL);#ifdef LOSCFG_SHELL(VOID)memcpy_s(seg->ownerName, OS_PCB_NAME_LEN, OS_PCB_FROM_PID(shm_perm.uid)->processName,OS_PCB_NAME_LEN);#endifbreak;case IPC_RMID://删除共享段ret = ShmPermCheck(seg, SHM_M);seg->status |= SHM_SEG_REMOVE;if (seg->ds.shm_nattch <= 0) {//没有任何进程在使用了ShmFreeSeg(seg);//释放 归还内存}break;case IPC_INFO://把内核空间的共享页数据拷贝到用户空间ret = LOS_ArchCopyToUser(buf, &g_shmInfo, sizeof(struct shminfo));ret = g_shmInfo.shmmni;break;case SHM_INFO:shmInfo.shm_rss = 0;shmInfo.shm_swp = 0;shmInfo.shm_tot = 0;shmInfo.swap_attempts = 0;shmInfo.swap_successes = 0;shmInfo.used_ids = ShmSegUsedCount();//在使用的seg数ret = LOS_ArchCopyToUser(buf, &shmInfo, sizeof(struct shm_info));//把内核空间的共享页数据拷贝到用户空间ret = g_shmInfo.shmmni;break;default:VM_ERR("the cmd(%d) is not supported!", cmd);ret = EINVAL;goto ERROR;}SYSV_SHM_UNLOCK();return ret;}
  • 第四步: 完事了解绑/删除,好聚好散还有下次,在ShmDt中主要干了解除映射LOS_ArchMmuUnmap这件事,没有了映射就不再有关系了,并且会检测到最后一个解除映射的进程时,会彻底释放掉这段共享内存ShmFreeSeg
    /*** @brief 当对共享存储的操作已经结束时,则调用shmdt与该存储段分离如果shmat成功执行,那么内核将使与该共享存储相关的shmid_ds结构中的shm_nattch计数器值减1* @attention 注意:这并不从系统中删除共享存储的标识符以及其相关的数据结构。共享存储的仍然存在,直至某个进程带IPC_RMID命令的调用shmctl特地删除共享存储为止* @param shmaddr * @return INT32 */INT32 ShmDt(const VOID *shmaddr){LosVmSpace *space = OsCurrProcessGet()->vmSpace;//获取进程空间(VOID)LOS_MuxAcquire(&space->regionMux);region = LOS_RegionFind(space, (VADDR_T)(UINTPTR)shmaddr);//找到线性区shmid = region->shmid;//线性区共享IDLOS_RbDelNode(&space->regionRbTree, &region->rbNode);//从红黑树和链表中摘除节点LOS_ArchMmuUnmap(&space->archMmu, region->range.base, region->range.size >> PAGE_SHIFT);//解除线性区的映射(VOID)LOS_MuxRelease(&space->regionMux);/* free it */free(region);//释放线性区所占内存池中的内存SYSV_SHM_LOCK();seg = ShmFindSeg(shmid);//找到seg,线性区和共享段的关系是 1:N 的关系,其他空间的线性区也会绑在共享段上ShmPagesRefDec(seg);//页面引用数 --seg->ds.shm_nattch--;//使用共享内存的进程数少了一个if ((seg->ds.shm_nattch <= 0) && //无任何进程使用共享内存(seg->status & SHM_SEG_REMOVE)) {//状态为删除时需要释放物理页内存了,否则其他进程还要继续使用共享内存ShmFreeSeg(seg);//释放seg 页框链表中的页框内存,再重置seg状态} else {seg->ds.shm_dtime = time(NULL);//记录分离的时间seg->ds.shm_lpid = LOS_GetCurrProcessID();//记录操作进程ID}SYSV_SHM_UNLOCK();

总结

看到这里你应该不会问共享内存的作用和为啥它是最快的进程间通讯方式了,如果还有这两个问题说明还要再看一遍 😛 ,另外细心的话会发现共享内存会有个小缺点,就是同时访问的问题,所以需要使用互斥锁来保证同时只有一个进程在使用,SYSV_SHM_LOCK和 SYSV_SHM_UNLOCK在以上的四个步骤中都有出现。

STATIC LosMux g_sysvShmMux; //互斥锁,共享内存本身并不保证操作的同步性,所以需用互斥锁
/* private macro */
#define SYSV_SHM_LOCK()     (VOID)LOS_MuxLock(&g_sysvShmMux, LOS_WAIT_FOREVER)	//申请永久等待锁
#define SYSV_SHM_UNLOCK()   (VOID)LOS_MuxUnlock(&g_sysvShmMux)	//释放锁

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN

图片

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往在这里插入图片描述

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

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

相关文章

看图学sql之sql中的子查询

&#xfeff;&#xfeff; &#xfeff;where子句子查询 语法&#xff1a; SELECT column_name [, column_name ] FROM table1 [, table2 ] WHERE column_name OPERATOR(SELECT column_name [, column_name ]FROM table1 [, table2 ][WHERE]) 子查询需要放在括号( )内。O…

解决git checkout -b 拉取远端某分支到本地时报错

问题描述 日常开发场景中&#xff0c;经常会出现切分支的情况&#xff0c;所以git checkout 命令是非常高频的 git checkout -b feature/xxx默认情况下&#xff0c;这条命令是基于当前所在分支来开辟新分支feature/xxx 但是&#xff0c;还有一些情况&#xff0c;我们需要基于…

appium下载及安装

下载地址&#xff1a;https://github.com/appium/appium-desktop/releases 双击安装就可以

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(三)---创建自定义激光雷达Componet组件

前言 本系列教程旨在使用UE5配置一个具备激光雷达深度摄像机的仿真小车&#xff0c;并使用通过跨平台的方式进行ROS2和UE5仿真的通讯&#xff0c;达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础&#xff0c;Nav2相关的学习教程可以参考本人的其他博…

数学建模学习(115):主成分分析(PCA)与Python实践

文章目录 一.主成分分析简介1.1 数学背景与维度诅咒1.2 PCA的定义与应用二.协方差矩阵——特征值和特征向量三.如何为数据集选择主成分数量四.特征提取方法五.LDA——与PCA的区别六.PCA的应用七.PCA在异常检测中的应用八.总结一.主成分分析简介 1.1 数学背景与维度诅咒 主成成…

视频智能分析平台烟火检测视频安防监控烟火算法识别应用方案

烟火检测算法的应用方案主要围绕其核心技术——深度学习&#xff08;特别是卷积神经网络CNN&#xff09;和计算机视觉技术展开&#xff0c;旨在实现对监控视频中的烟雾和火焰进行实时、准确的检测与识别。以下是一个详细的烟火检测算法应用方案&#xff1a; 一、技术原理 烟火…

高并发集群饿了么后端的登录模块

高并发集群饿了么后端的登录模块 1.数据库 非交互式python&#xff1a; 非交互式: 2.数据库的负载均衡&#xff1a;阿里巴巴的mycat 修改配置文件 /usr/local/mycat/conf/server.xml :对外的账号 密码 数据库 /usr/local/mycat/conf/schema.xml 如果出现启动异常&…

【微信小程序】自定义组件 - 数据监听器

1. 什么是数据监听器 2. 数据监听器的基本用法 组件的 UI 结构如下&#xff1a; 组件的 .js 文件代码如下&#xff1a; 3. 监听对象属性的变化 数据监听器 - 案例 案例效果 2. 渲染 UI 结构 3. 定义 button 的事件处理函数 4. 监听对象中指定属性的变化 5. 监听对象中所…

readpaper在读论文时候的默认规定

红色代表主旨思想 蓝色代表专业名词解析

【MySQL】 黑马 MySQL进阶 笔记

文章目录 存储引擎MySQL的体系结构存储引擎概念存储引擎特点InnoDBMyISAMMemory 存储引擎选择 索引概述结构B Tree(多路平衡查找树)B TreeHash为什么InnoDB存储引擎选择使用Btree索引结构? 分类思考题 语法SQL性能分析&#xff08;索引相关&#xff09;SQL执行频率慢查询日志p…

XSS game复现(DOM型)

目录 1.Ma Spaghet! 2.Jefff 3.Ugandan Knuckles 4.Ricardo Milos 5.Ah Thats Hawt 6.Ligma 7.Mafia 8.Ok, Boomer 1.Ma Spaghet! 通过简单的尝试发现传递参数可以直接进入h2标签 接下来我们尝试传入一个alert(1) 可以看到并没有触发。原因是在innerHTML中官方禁用了sc…

MySQL InnoDB引擎四大特性ACID实现方案分析

文章目录 概要InnoDb引擎ACID模型的实现方案小结 概要 对于Mysql&#xff0c;事物的支撑并不依赖于Server层&#xff0c;不同的存储引擎对于事物的支持也不一样&#xff0c;对于我们常用的InnoDB引擎&#xff0c;其提供了一套基于【ACID模型】的事物完整的解决方案。为什么MyIS…

【AI Agent极限挑战赛】三大赛题揭晓

由AIGC开放社区联合联想拯救者、英特尔共同主办的【2024 AI Agent极限挑战赛】于8月17日在上海中庚聚龙酒店成功举办。赛事全面考察参赛者将AI技术应用于实际问题的能力。比赛内容包括对大语言模型的理解、提示词&#xff08;Prompt&#xff09;的结构化调优技术、个人助理Agen…

如何使用ssm实现在线云音乐系统的设计与实现

TOC ssm042在线云音乐系统的设计与实现jsp 第1章 绪论 1.1背景及意义 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于在线云音乐系统所牵扯的管理及数据保存都是非常多的&#xff0c;例如用户管理、歌曲管理、推荐管理等&#xff0c;这给管理者的工作带来了巨…

基于华为昇腾910B和LLaMA Factory多卡微调的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

uniapp点击预览图片,两种效果

背景&#xff1a; 在使用uniapp框架中&#xff0c;我们对图片的展示需要点击放大展示(单张)&#xff1b;如果是多张图片&#xff0c;要支持左右滑动查看多张图片(多张)。 官网链接&#xff1a;点击跳转官网 一、单张&#xff0c;点击放大 代码&#xff1a; <template> …

Kubernetes服务发布基础

通过k8s的调度&#xff0c;我们可以成功的将服务部署到Kubernetes&#xff0c;应用部署后&#xff0c;最重要的就是对用户开放。 在传统的架构中&#xff0c;用户访问公司内的服务可能通过了多层代理、网关、防火墙等。在Kubernetes中&#xff0c;访问Kubernetes中的的应用同样…

Windows下使用QT5.14.2编译MySQL8.0对应的最新64位驱动程序步骤

不得不说mysql更新的速度是真的快&#xff0c;最近一两年都更新了好几个的小版本了。如果安装了高版本的 mysql软件&#xff0c;低版本的驱动就不支持了&#xff0c;因此需要重新使用QT来编译对应的mysql驱动。具体办法如下&#xff1a; 1、官网下载最新的mysql8.0安装包。下载…

ABAP 引用变量(TYPE REF TO )和字段符号(FIELD-SYMBOLS)全集

本文主要是记录了一些关于ABAP 引用变量(TYPE REF TO )和字段符号(FIELD-SYMBOLS)的相关内容&#xff0c;有些参考来自多个博客&#xff0c;以及官方文档 文章目录 FIELD-SYMBOLS字段符号官方文档Declaring Field SymbolsTyping Field Symbols 引用变量文章1引用变量介绍测试程…

Linux文件属性和打包压缩详解

1、文件属性体系 1.1 文件系统概述 [rootyunwei /]# ls -lhi 总用量 72K3505 lrwxrwxrwx. 1 root root 7 3月 7 2019 bin -> usr/bin 262152 dr-xr-xr-x. 5 root root 4.0K 12月 19 16:00 boot 399635 drwxr-xr-x 2 root root 4.0K 11月 5 2019 data1026 drw…