linux 内核 ida机制分析
在描述ida之前,需要读者对linux 内核的radix-tree有一定的了解。关于radix-tree(基数树)的描述,作者在之前有专门的文章对其进行描述,这里不再赘述。
IDA是什么?内核文档中解释如下:
/*** IDA description** The IDA is an ID allocator which does not provide the ability to associate an ID with a pointer. * As such, it only needs to store one bit per ID, and so is more space efficient than an IDR. To use an IDA,* * define it using DEFINE_IDA() (or embed a &struct ida in a data structure,then initialise it using ida_init()). * To allocate a new ID, call ida_simple_get(). To free an ID, call ida_simple_remove().** If you have more complex locking requirements, use a loop around ida_pre_get() and ida_get_new() to allocate a new ID. * Then use ida_remove() to free an ID. * You must make sure that ida_get_new() and ida_remove() cannot be called at the same time as each other for the same IDA.** You can also use ida_get_new_above() if you need an ID to be allocated above a particular number. * ida_destroy() can be used to dispose of an IDA without needing to free the individual IDs in it. * You can use ida_is_empty() to find out whether the IDA has any IDs currently allocated.** IDs are currently limited to the range [0-INT_MAX]. * If this is an awkward limitation, it should be quite straightforward to raise the maximum.*/
ida只处理id的分配,不关注与id关联的item,id在shift=0层radix_tree_node节点上的slots[]无需存储item所以就就空闲出来了,ida在对应的slots[]上存放bitmap,因为标记bitmap内的id的分配情况。这样整个ida的radix-tree的深度就缩减了。
bitmap长度为 IDA_BITMAP_BITS(128),id去除bitmap标记的位后,index为id/IDA_BITMAP_BITS。
将index作为起始id,[index,IDA_MAX)范围内 在radix-tree中进行处理id,分配完成后将bitmap中id%IDA_BITMAP_BITS的bit位置位,表示数据已被分配。
idr或者ida是在[start,end)范围内分配id,根据radix-tree中id分配情况,最终分配出来的id可能>=start.
1、数据结构
/** IDA - IDR based id allocator, use when translation from id to pointer isn't necessary.*/#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk *//*IDA_CHUNK所需字节数*/
#define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long)) /*128/64=2*/
/*IDA_CHUNK所需bit位数*/
#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8) /*2*8*8=128*//** The IDA is even shorter since it uses a bitmap at the last level.*/
#define IDA_INDEX_BITS (8 * sizeof(int) - 1 - ilog2(IDA_BITMAP_BITS)) //8*4-1-7=32-8=24
#define IDA_MAX_PATH (DIV_ROUND_UP(IDA_INDEX_BITS, RADIX_TREE_MAP_SHIFT)) //DIV_ROUND_UP(24,6) = 4
#define IDA_PRELOAD_SIZE (IDA_MAX_PATH * 2 - 1) //4*2-1=7/*ida radix-tree树最大深度为4,4*6=24位*/
#define IDA_MAX (0x80000000U / IDA_BITMAP_BITS) //0x80000000U/128(0x80)=0x1000000 (16,777,216)struct ida_bitmap {unsigned long bitmap[IDA_BITMAP_LONGS]; //bitmap[2]
};/*per-cpu变量*/
DECLARE_PER_CPU(struct ida_bitmap *, ida_bitmap);struct ida {struct radix_tree_root ida_rt;
};
2、接口说明
2.1、ida初始化
/*定义和初始化ida*/
#define DEFINE_IDA(name) struct ida name = IDA_INIT#define IDA_INIT { \.ida_rt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT), \
}/*初始化ida*/
static inline void ida_init(struct ida *ida)
{INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
}
2.2、ida分配id(ida_pre_get/ida_get_new/ida_get_new_above)
/*** ida_pre_get - reserve resources for ida allocation* @ida: ida handle* @gfp: memory allocation flags** This function should be called before calling ida_get_new_above(). If it* is unable to allocate memory, it will return %0. On success, it returns %1.*/
int ida_pre_get(struct ida *ida, gfp_t gfp)
{/** The IDA API has no preload_end() equivalent. Instead,* ida_get_new() can return -EAGAIN, prompting the caller* to return to the ida_pre_get() step.*/if (!__radix_tree_preload(gfp, IDA_PRELOAD_SIZE)) //7preempt_enable();if (!this_cpu_read(ida_bitmap)) {/*为ida_bitmap分配空间*/struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp);if (!bitmap)return 0;if (this_cpu_cmpxchg(ida_bitmap, NULL, bitmap))kfree(bitmap);}return 1;
}注意:
1)、ida_get_new从0开始分配id,ida_get_new_above从传入的参数start开始分配id。
2)、ida_get_new_above再从void *切换到bitmap时,依赖于ida_pre_get为ida_bitmap分配的空间。/*** ida_get_new - allocate new ID* @ida: idr handle* @p_id: pointer to the allocated handle** Simple wrapper around ida_get_new_above() w/ @starting_id of zero.*/
static inline int ida_get_new(struct ida *ida, int *p_id)
{return ida_get_new_above(ida, 0, p_id);
}/*** ida_get_new_above - allocate new ID above or equal to a start id* @ida: ida handle* @start: id to start search at* @id: pointer to the allocated handle** Allocate new ID above or equal to @start. It should be called* with any required locks to ensure that concurrent calls to* ida_get_new_above() / ida_get_new() / ida_remove() are not allowed.* Consider using ida_simple_get() if you do not have complex locking* requirements.** If memory is required, it will return %-EAGAIN, you should unlock* and go back to the ida_pre_get() call. If the ida is full, it will* return %-ENOSPC. On success, it will return 0.** @id returns a value in the range @start ... %0x7fffffff.*/
int ida_get_new_above(struct ida *ida, int start, int *id)
{struct radix_tree_root *root = &ida->ida_rt;void __rcu **slot; /*二级指针*/struct radix_tree_iter iter;struct ida_bitmap *bitmap;unsigned long index;unsigned bit, ebit;int new;index = start / IDA_BITMAP_BITS;bit = start % IDA_BITMAP_BITS;/*为什么 + RADIX_TREE_EXCEPTIONAL_SHIFT???,因为ebit<IDA_BITMAP_BITS时 slots[]中存放的是一个void *的数据,为了和slots[]中存放bitmap进行区分,void *数据被设置了 RADIX_TREE_EXCEPTIONAL_ENTRY(2),导致void*的低2bit无法使用,所以最开始 + RADIX_TREE_EXCEPTIONAL_SHIFT*/ebit = bit + RADIX_TREE_EXCEPTIONAL_SHIFT;slot = radix_tree_iter_init(&iter, index);for (;;) {if (slot) /*后面的循环会使用该条件,slot有效,当期slots[]无空闲数据,查找相邻slots[]是否有空闲数据*/slot = radix_tree_next_slot(slot, &iter,RADIX_TREE_ITER_TAGGED);if (!slot) {/*在[index,IDA_MAX)之间分配数据,分配出来的数据在iter->index更新,返回 &slots[offset],注意slot是二级指针*/slot = idr_get_free(root, &iter, GFP_NOWAIT, IDA_MAX);if (IS_ERR(slot)) {if (slot == ERR_PTR(-ENOMEM))return -EAGAIN;return PTR_ERR(slot);}}if (iter.index > index) { /*分配出来的iter.index > index */bit = 0;ebit = RADIX_TREE_EXCEPTIONAL_SHIFT;}new = iter.index * IDA_BITMAP_BITS; /*数据还原*/bitmap = rcu_dereference_raw(*slot); /*在ida中slots[]中存放bitmap*/if (radix_tree_exception(bitmap)) { /*4字节未对齐,slots[]中存放的不是bitmap而是使用的void *数据*/unsigned long tmp = (unsigned long)bitmap;/*从ebit开始找zero bit位*/ebit = find_next_zero_bit(&tmp, BITS_PER_LONG, ebit);if (ebit < BITS_PER_LONG) {tmp |= 1UL << ebit; /*将这位置1*/rcu_assign_pointer(*slot, (void *)tmp); /*将数据重新写回slots[]中*/*id = new + ebit - RADIX_TREE_EXCEPTIONAL_SHIFT;return 0;}//ebit >= BITS_PER_LONG,将ida_bitmap申请的地址赋值给bitmap,ida_bitmap赋值为NULLbitmap = this_cpu_xchg(ida_bitmap, NULL);if (!bitmap)return -EAGAIN;/*将bitmap赋值给*slot,用bitmap替换到之前的unsigned long数据,会去掉最低2bit的 RADIX_TREE_EXCEPTIONAL_ENTRY标志*/memset(bitmap, 0, sizeof(*bitmap));bitmap->bitmap[0] = tmp >> RADIX_TREE_EXCEPTIONAL_SHIFT; /*会去掉最低2bit的 RADIX_TREE_EXCEPTIONAL_ENTRY标志*/rcu_assign_pointer(*slot, bitmap);}/*bitma有效,slots[]中存放的是bitmap地址*/if (bitmap) {/*从bitmap中寻找空闲位*/bit = find_next_zero_bit(bitmap->bitmap,IDA_BITMAP_BITS/*128*/, bit);new += bit;if (new < 0)return -ENOSPC;if (bit == IDA_BITMAP_BITS)continue; /*当期slots[]无空闲数据,查找相邻slots[]是否有空闲数据*/__set_bit(bit, bitmap->bitmap); /*设置当前bit 位*/if (bitmap_full(bitmap->bitmap, IDA_BITMAP_BITS))radix_tree_iter_tag_clear(root, &iter,IDR_FREE); /*当前节点bitmap内无任何空闲位,清除当前节点tags[IDR_FREE],表示该node内无空闲*/} else { /*bitmap无效,说明当前slots[]还未被使用,可分配*/new += bit;if (new < 0)return -ENOSPC;if (ebit < BITS_PER_LONG) {/*直接存放(void *)数据到slots[]中去,但是标记为RADIX_TREE_EXCEPTIONAL_ENTRY 异常entry和bitmap进行区分通过上面的代码可知,只有void *数据内无空闲位或ebit超过BITS_PER_LONG(64)时才会用bitmap来替换void *数据*/bitmap = (void *)((1UL << ebit) | RADIX_TREE_EXCEPTIONAL_ENTRY);radix_tree_iter_replace(root, &iter, slot, bitmap);*id = new;return 0;}/*ebit >= BITS_PER_LONG*/bitmap = this_cpu_xchg(ida_bitmap, NULL);if (!bitmap)return -EAGAIN;/*使用bitmap而非void *数据*/memset(bitmap, 0, sizeof(*bitmap));__set_bit(bit, bitmap->bitmap);radix_tree_iter_replace(root, &iter, slot, bitmap);}*id = new;return 0;}
}
2.3、ida删除id(ida_remove)
/*** ida_remove - Free the given ID* @ida: ida handle* @id: ID to free** This function should not be called at the same time as ida_get_new_above().*/
void ida_remove(struct ida *ida, int id)
{unsigned long index = id / IDA_BITMAP_BITS;unsigned offset = id % IDA_BITMAP_BITS;struct ida_bitmap *bitmap;unsigned long *btmp;struct radix_tree_iter iter;void __rcu **slot;/*返回index对应的 &slots[offset]地址并且设置iter*/slot = radix_tree_iter_lookup(&ida->ida_rt, &iter, index);if (!slot)goto err;bitmap = rcu_dereference_raw(*slot);if (radix_tree_exception(bitmap)) { /*void *数据*/btmp = (unsigned long *)slot;offset += RADIX_TREE_EXCEPTIONAL_SHIFT; /if (offset >= BITS_PER_LONG)goto err;} else { /*bitmap数据*/btmp = bitmap->bitmap;}if (!test_bit(offset, btmp))goto err;__clear_bit(offset, btmp);radix_tree_iter_tag_set(&ida->ida_rt, &iter, IDR_FREE);/*删除id后,检查是否能够删除整个node*/if (radix_tree_exception(bitmap)) {if (rcu_dereference_raw(*slot) == (void *)RADIX_TREE_EXCEPTIONAL_ENTRY) /*无任何被使用,删除node*/radix_tree_iter_delete(&ida->ida_rt, &iter, slot);} else if (bitmap_empty(btmp, IDA_BITMAP_BITS)) {kfree(bitmap);radix_tree_iter_delete(&ida->ida_rt, &iter, slot);}return;err:WARN(1, "ida_remove called for id=%d which is not allocated.\n", id);
}
2.4、ida分配id (ida_simple_get)
ida_simple_get内部在关开中断的条件下调用的ida_pre_get ida_get_new_above来进行id分配.
/*** ida_simple_get - get a new id.* @ida: the (initialized) ida.* @start: the minimum id (inclusive, < 0x8000000)* @end: the maximum id (exclusive, < 0x8000000 or 0)* @gfp_mask: memory allocation flags** Allocates an id in the range start <= id < end, or returns -ENOSPC.* On memory allocation failure, returns -ENOMEM.** Compared to ida_get_new_above() this function does its own locking, and* should be used unless there are special requirements.** Use ida_simple_remove() to get rid of an id.*/
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,gfp_t gfp_mask)
{int ret, id;unsigned int max;unsigned long flags;BUG_ON((int)start < 0);BUG_ON((int)end < 0);if (end == 0)max = 0x80000000;else {BUG_ON(end < start);max = end - 1;}again:if (!ida_pre_get(ida, gfp_mask))return -ENOMEM;spin_lock_irqsave(&simple_ida_lock, flags); /*关闭中断*/ret = ida_get_new_above(ida, start, &id);if (!ret) {if (id > max) {ida_remove(ida, id);ret = -ENOSPC;} else {ret = id;}}spin_unlock_irqrestore(&simple_ida_lock, flags); /*恢复中断*/if (unlikely(ret == -EAGAIN))goto again;return ret;
}
2.5、ida释放id(ida_simple_remove)
ida_simple_remove内部是在关/开中断条件下调用的ida_remove来释放id.
/*** ida_simple_remove - remove an allocated id.* @ida: the (initialized) ida.* @id: the id returned by ida_simple_get.** Use to release an id allocated with ida_simple_get().** Compared to ida_remove() this function does its own locking, and should be* used unless there are special requirements.*/
void ida_simple_remove(struct ida *ida, unsigned int id)
{unsigned long flags;BUG_ON((int)id < 0);spin_lock_irqsave(&simple_ida_lock, flags); /*关中断*/ida_remove(ida, id);spin_unlock_irqrestore(&simple_ida_lock, flags); /*开中断*/
}
2.6、注销ida(ida_destroy)
/*** ida_destroy - Free the contents of an ida* @ida: ida handle** Calling this function releases all resources associated with an IDA. When* this call returns, the IDA is empty and can be reused or freed. The caller* should not allow ida_remove() or ida_get_new_above() to be called at the* same time.*/
void ida_destroy(struct ida *ida)
{struct radix_tree_iter iter;void __rcu **slot;/*遍历radix-tree slots[]*/radix_tree_for_each_slot(slot, &ida->ida_rt, &iter, 0) {struct ida_bitmap *bitmap = rcu_dereference_raw(*slot);if (!radix_tree_exception(bitmap)) /*bitmap*/kfree(bitmap);radix_tree_iter_delete(&ida->ida_rt, &iter, slot);}
}
3、示例
ida分配数据后radix-tree形态如下:
相关文章:
linux 内核 ida机制分析
在描述ida之前,需要读者对linux 内核的radix-tree有一定的了解。关于radix-tree(基数树)的描述,作者在之前有专门的文章对其进行描述,这里不再赘述。 IDA是什么?内核文档中解释如下: /*** IDA description** The IDA is an ID allocator which does not provide the ab…...
linux-定时任务清理buffer、cache
在清理 buffer 和 cache 之前,调用 sync 命令是一个好习惯。sync 会将文件系统缓冲区中的数据强制写入磁盘,确保数据的一致性,避免数据丢失的风险。以下是改进后的脚本,增加了多个 sync 语句: 1、脚本内容:…...
Linux常用命令整理
Linux 系统提供了大量常用命令行工具,涵盖文件操作、权限管理、网络诊断、软件安装、系统监控、脚本编程等各个方面。下面按照不同功能类别,整理常用的 Linux 命令及其中文说明和使用示例。 文件与目录操作 ● ls:列出目录内容,用于显示指定目录下的文件和子目录。常用参数…...
Python爬虫第14节-如何爬取Ajax的数据
目录 前言 一、什么是Ajax 1.1 具体举例 1.2 基本原理 二、Ajax的分析 2.1 查看请求 2.2 过滤请求 三、解析提取Ajax 结果 3.1 分析请求 3.2 分析响应 四、Ajax抓取实战 前言 咱们在使用requests抓取网页的时候,常常会发现,得到的结果和在浏览…...
mac上面使用zip命令压缩一劳永逸
问题 需要将当前目录的文件和目录(包含隐藏目录)都要压缩近一个zip包,但同时部分目录我不想压缩进去例如:.idea这个种idea的配置目录就不想压缩进zip包。 命令 zip -r flask-dev.zip . -x "*.idea*"-r:递归目录.:当前…...
错误地使用了 app.use() 来注册全局组件
我是import globalComponent from "/components"; /* eslint-disable */ // ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 export {}; /* prettier-ignore */ declare module vue { export interface…...
Python Django基于协同过滤算法的招聘信息推荐系统【附源码、文档说明】
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
鹰角:EMR Serverless Spark 在《明日方舟》游戏业务的应用
作者:鹰角网络高级大数据研发 茅旭辉 背景介绍 鹰角网络是一家年轻且富有创新的游戏公司,致力于开发充满挑战性和艺术价值的游戏产品。公司目前涵盖了游戏开发、运营和发行的全生命周期业务。随着业务的扩展,鹰角网络从单一爆款游戏发展到多…...
C语言学习之两个数值交换的算法
前言:本篇文章仅仅是作为作者复习使用 在C语言中,交换两个两个变量的数值是很常见的应用。在学习到指针的时候,我们已经掌握了几种交换的算法了。今天我来做一个小汇总 1创建第三个变量 缺点:需要创造第三个变量 2加减交换 缺点…...
CExercise_13_1排序算法_2归并排序
题目:CExercise_ 请手动实现归并排序算法: void merge_sort(int arr[], int len) 如果学有余力,不妨尝试一下多种临时数组的方式: 1.局部变量数组 2.全局变量数组 3.堆数组 关键点 分析: : 代码 代码块解决…...
富斯i6遥控器,无法切换通道解决办法
开机后长按【OK】键,进入设置 按【DOWN】选择【setup】 点击【ok】进入设置 再点击【OK】进入Reverse 将2设置为下,长按【cancel】保存,返回到设置 进入【Aux.channels】 将第二行【Source】设置为【Source SwC】,长按【CANCEL】保存并返回。…...
Maven 编译指定模版
背景 基于SpringCloud 做的微服务项目,很多都是依赖公共模块下的包,并且多模板都是在一个项目下的。 问题 每次打包都很编译整个项目下的所有模块。这样太耗时间了,把流水线的时间拖的太长了。 解决方案 在maven打包时,我们选…...
solr安装及ik中文分词器配置
提示:solr9.x版本需要jdk17,solr8.x版本需要jdk8 1、Solr 简介 Solr 是Apache 下的一个顶级开源项目,采用 Java 开发,它是基于 Lucene 的全文搜索服务器。Solr 提供了比 Lucene 更为丰富的查询语句,同时实现了可配置、…...
详解LeetCode中用字符串实现整数相加,字符串转整数及其溢出处理详解
目录 题目背景 代码整体逻辑 变量初始化 逐位相加过程 处理最后进位 结果反转 示例演示 总结 在LeetCode中,有一道经典的算法题是实现两个字符串形式的非负整数相加,今天我们就来深入分析一段用C实现该功能的代码,探究其背后的逻辑与…...
vue学习笔记06
学习的课程地址:老杜Vue视频教程,Vue2,Vue3实战精讲,一套通关vue_哔哩哔哩_bilibili 1、vue程序初体验 2、vue核心技术(基础) 3、Vue组件化 前面参见: vue学习笔记01 vue学习笔记02 vue学习笔记03 vue学习笔记…...
如何查看自己抖音的IP属地?详细教程及如何修改
在当今互联网时代,IP属地信息已成为各大社交平台(如抖音、微博、快手等)展示用户真实网络位置的重要功能。以下是关于如何查看抖音IP属地的详细教程及常见问题解答,帮助您快速了解相关信息: 一、如何查看抖音账号的IP属…...
熟悉Linux下的编程
可能 目录 熟悉Linux下Python编程的含义及与非Linux环境编程的区别 一、核心含义解析 二、与非Linux环境的关键区别 三、典型应用场景对比 四、能力培养建议 openfoem的下载之路: 方法一:使用cd命令 方法二:使用快捷方式 方法三&am…...
Uniapp:获取当前定位坐标
目录 一、出现场景二、具体使用 一、出现场景 在项目的开发中,会出现打卡、定位当前位置的功能,那我们如何获取当前位置呢?这就需要使用getLocation来获取当前位置坐标 二、具体使用 uni.getLocation({type: wgs84, // 返回可以用于uni.op…...
GitHub实用手册
文章目录 一、GitHub 的定义二、GitHub 的主要功能三、GitHub 的优势四、GitHub 的使用相关工具GitSourcetreeGithub-Desktop 一、GitHub 的定义 GitHub 是一个基于 Git 的分布式版本控制系统,它允许开发者在本地和远程仓库中管理代码版本,支持多人协作…...
【从零实现高并发内存池】Central Cache从理解设计到全面实现
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
Dijkstra算法求解最短路径—— 从零开始的图论讲解(2)
前言 在本系列第一期:从零开始的图论讲解(1)——图的概念,图的存储,图的遍历与图的拓扑排序-CSDN博客 笔者给大家介绍了 图的概念,如何存图,如何简单遍历图,已经什么是图的拓扑排序 按照之前的学习规划,今天笔者将继续带大家深入了解图论中的一个核心问题&#x…...
Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7)
Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7),下个月就是 RC1,紧接着就是 GA!,对于我们 Java 开发者来说,这绝对是个值得关注的好消息! 但是对于 Java 学习者来说,…...
如何从 GitHub 镜像仓库到极狐GitLab?
最近 GitHub 封禁中国用户的事情闹得沸沸扬扬,虽然官方发布的报道说中国用户被限制登录是因为配置错误导致,已经撤回了更新,中国用户已经可以正常使用。但是这就像横在国内开发者和企业头上的“达摩克利斯之剑”。为了避免 GitHub 不可用而带…...
大象机器人推出myCobot 280 RDK X5,携手地瓜机器人共建智能教育机
摘要 大象机器人全新推出轻量级高性能教育机械臂 myCobot 280 RDK X5,该产品集成地瓜机器人 RDK X5 开发者套件,深度整合双方在硬件研发与智能计算领域的技术优势,实现芯片架构、软件算法、硬件结构的全栈自主研发。作为国内教育机器人生态合…...
在Android Studio中,`Settings`里的Gradle路径、环境变量以及`gradle - wrapper.properties`文件关联
在Android Studio中,Settings里的Gradle路径、环境变量以及gradle - wrapper.properties文件关联 Android Studio中Settings里的Gradle路径 在Android Studio的Settings(Preferences ) -> Build, Execution, Deployment -> Build Tools -> Gradle 中: Use defau…...
用react 写一个可左右滑动的柱状图
效果图 目录 效果图 ✅ 项目结构 🚀 创建项目步骤 1️⃣ 打开终端或命令行,创建新项目: 2️⃣ 安装 recharts 图表库: 3️⃣ 替换默认代码: 4️⃣ 启动项目: ✅ 项目结构 scrollable-bar-chart/ ├…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——MIPI LCD测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:www.alientek.com 3)全套实验源码手册视频下载:正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——MIPI LCD测试4.3 MIPI LCD测试4.3.1 使…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——RS485串口测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:www.alientek.com 3)全套实验源码手册视频下载:正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——RS485串口测试 第四章 ATK-DLMP257B功能…...
Sui 的工具生态简化了游戏开发者的 Web3 集成流程
希望利用 Web3 独特协同效应的游戏开发者,常常在强大的区块链功能与流畅的游戏体验之间难以权衡。许多区块链方案要求大幅重构游戏基础架构,增加了开发难度,甚至需要学习全新的智能合约语言。而 Sui 通过直观的工具消除这一阻力,使…...
Vue 3 的组合式 API-hooks
Vue 3 的组合式 API 组合式 API 是 Vue 3 的核心特性之一,它允许开发者将组件的逻辑拆分为可复用的函数。组合式 API 的主要特点是 逻辑复用:将逻辑提取到独立的函数中,方便在多个组件中复用。组织清晰:将相关的逻辑分组&#x…...
AOSP Android14 Launcher3——底部任务栏Taskbar详解
前言:Launcher3中底部Taskbar和Navbar,或者说中文里面的术语导航栏,这几个词是很容易让人混淆的地方。本文要介绍的是Taskbar。从字面上意思来看,Taskbar就是任务栏,任务栏是Launcher3中一个重要的组件,尤其…...
QGraphicsView、QGraphicsScene和QGraphicsItem图形视图框架(五)QGraphicsView的缩放和移动
QGraphicsView自带滚动条的显示,但是大部分的需求样式都不需要滚动条,并且要通过鼠标来控制视图的缩放和移动。需要重写QGraphicsView实现。 一、相关函数 1.scale void QGraphicsView::scale(qreal sx, qreal sy) 按(sx,sy&…...
算法——果蝇算法
果蝇算法(Fruit Fly Optimization Algorithm,FOA)是一种受果蝇觅食行为启发而开发的群智能优化算法。以下从算法原理、算法流程、算法特点等方面为你详细讲述: 算法原理 果蝇本身具有优于其他物种的嗅觉和视觉。在觅食过程中&am…...
重返JAVA之路——图书管理系统
目录 一、功能介绍 二、设计模块 三、系统构建 1.book模块 2.operation模块 输入循环和验证 查找图书并处理借阅状态 未找到图书的处理 查找删除图书功能实现 未找到图书的处理 图书查找与归还 work方法实现图书信息输出 3. user模块实现 四、主菜单 一、功能介绍 …...
【16】数据结构之基于树的排序算法篇章
目录标题 选择排序简单选择排序树形选择排序 堆排序堆的定义Heap小跟堆大根堆堆的存储堆的代码设计堆排序的代码设计 排序算法综合比较 选择排序 基本思想:从待排序的序列中选出最大值或最小值,交换该元素与待排序序列的头部元素,对剩下的元…...
Uniapp:确认框
目录 一、 出现场景二、 效果展示三、具体使用 一、 出现场景 在项目的开发中,会经常出现删除数据的情况,如果直接删除的话,可能会存在误删,用户体验不好,所以需要增加一个消息提示,提醒用户是否删除。 二…...
pyswmm实现洪涝模拟
准备好.inp文件作为SWMM模型输入,调用pyswmm模块执行模拟,返回节点溢流量(flooding)作为积水量的初步表征。 代码: from pyswmm import Simulation, Nodes import pandas as pddef run_swmm_simulation(inp_file, ou…...
My Diary Pro:记录生活,珍藏回忆
我的日记My Diary Pro是一个非常好用的手机日记软件,可以使用它来记录每日生活日常,不少的用户可能都知道在生活之中可能会发生一些比较的重要的事情,实际上我们都可以将这些内容记录下来。包括个人观点,旅行游记,心情…...
CSRF(跨站请求伪造)漏洞概述
CSRF(跨站请求伪造)漏洞概述 一、什么是 CSRF 攻击者诱导已登录用户在不知情的情况下,对受信任网站执行未授权操作。 简单说:你登录着网站A,攻击者诱导你访问某个恶意链接,使网站A误以为是你自己发出的操作(比…...
[Java实战经验]对象拷贝
目录 谨慎重写clone方法重写clone()支持深拷贝带来的问题 合适的深拷贝 首先,对于不可变的类,我们不应该实现Cloneable接口,因为不可变类不需要拷贝,直接引用即可,实现Cloneable接口只会造成浪费。 对于Java可变类来说…...
WAF防火墙:构筑Web应用安全的“隐形护盾”
在数字化时代,Web应用已成为企业服务与用户交互的核心窗口。然而,随之而来的SQL注入、跨站脚本攻击(XSS)、DDoS攻击等威胁,时刻考验着网站的安全防线。Web应用防火墙(WAF)作为关键防护工具&…...
开源智慧巡检——无人机油田AI视频监控的未来之力
油田巡检,关乎能源命脉,却常受困于广袤地形、高危环境和人工效率瓶颈。管道泄漏、设备故障、非法闯入——这些隐患稍有疏忽,便可能酿成大患。传统巡检已无法满足现代油田对安全与效率的需求,而无人机油田巡检系统正以智能化之力重…...
【2025年泰迪杯数据挖掘挑战赛】B题 完整论文 模型建立与求解
目录 2025年泰迪杯数据挖掘挑战赛 B题完整论文:建模与求解 Matlab代码一、问题重述二、模型假设与符号说明2.1 模型基本假设2.2 符号说明 三、数据预处理**问题一:志愿者身体活动信息的统计分析****问题二:身体活动MET值的实时估计模型构建**…...
Chromium 134 编译指南 macOS篇:安装 Xcode(二)
1. 引言 在Chromium开发的征程中,为macOS平台构建正确的开发环境是成功编译的关键基础。继上一篇系统环境准备后,本文将重点介绍Xcode的安装与配置过程。作为macOS上不可或缺的集成开发环境(IDE),Xcode为Chromium 134的编译提供了必要的编译…...
软件定义网络(SDN):重塑未来网络的革命性架构
在当今数字化时代,网络已成为企业、云计算、5G通信和物联网(IoT)的核心基础设施。然而,传统网络架构由于其封闭、静态和分布式的特性,难以应对快速变化的业务需求。软件定义网络(Software-Defined Networki…...
Java虚拟机面试题:类加载机制
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
OCCT 入门(3)核心模块与架构
文章目录 一、核心模块与架构1、架构概述2、核心模块3、数据流转3.1、几何创建(Geometric Primitives)3.2、拓扑构建(Topology Construction)3.3、模型处理(Modeling Algorithms)3.4、可视化(Vi…...
MAC-需求:10万订单异步执行库存扣减、短信通知。
批量任务并行处理 实现,通过拆分任务、异步执行和线程池管理提升处理。 10万订单异步处理方案设计 基于图中代码的批量处理框架,结合订单业务需求,以下是 库存扣减与短信通知的异步实现: 1. 代码实现(基于原有框架改造) @Service public…...
ArrayList vs LinkedList,HashMap vs TreeMap:如何选择最适合的集合类?
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 在 Java 开发中,集合类的选择直接影响程序的性能和代码的可维护性。不同的数据结构适用于不同的场景,盲目使用可能导致内存浪费、性能…...
使用Form.List且有Select组件
当在使用Form.List组件,且组件中有Select选项时,针对每一次选择,都要过滤掉那些已经选择过的选项,可能遇到的问题: 直接过滤会将每一个Select中的options选项都过滤掉,无法正常展示选择的选项 解决办法&a…...