轻量级C通用库Klib解读 —— kalloc
前言
Klib是一个独立的轻量级c通用库,里面大多数组件除了C标准库外不包含外部库,想用对应组件直接拷贝对应文件即可使用。
该库致力于高效和较小的内存占用,其中部分组件(如khash、kbtree、ksort、kvec),无论是内存还是速度方面,都是所有编程语言中相似算法或数据结构最高效的实现之一。
kalloc
源代码在这里,还有对应的.c文件
这是一个内存管理模块,可以实现类似操作系统那样“当你申请一小块内存时就从可用的大内存块里分一部分给你”的效果
整个模块分为两部分:
- 底层的内存块管理及其API
- 利用内存块管理的一个小内存池
内存块管理:void *km
数据结构主体
kmem_t
:隐藏的主体结构,接口里的void *
基本都是它,负责管理内存块
内存中连续的比较大的一块内存,代码中叫做core
申请与分配内存块时基本是按照header_t
大小的整数倍去处理的,所以把sizeof(header_t)
叫做一个内存单元unit
typedef struct header_t {size_t size;struct header_t *ptr;
} header_t;typedef struct {void *par;size_t min_core_size;header_t base, *loop_head, *core_head; /* base is a zero-sized block always kept in the loop */
} kmem_t;
header_t
:内存块使用的链表基础结构size
:内存块大小(单位为unit)ptr
:指向下一块内存
kmem_t
:包含一个带头节点的单向循环loop链表(记录内存块中的可用内存块的信息),和一个单向不循环core链表(记录整体内存块信息)par
:父指针(parent),可指向另一个kmem_t
结构。如果不为空则申请内存时是在父结构的内存块中申请内存给自己使用,释放内存时归还给父结构min_core_size
:最小core大小,默认为219=512k(单位为unit)base
:loop链表的头节点,大小size
永远为0,永远在loop链表中loop_head
:loop链表头指针core_head
:core链表头指针(总是指向最新申请的core)
注:上图为内存结构示意图,假设sizeof(size_t) = 4, sizeof(header_t) = 8
橙黄色箭头表示单向不循环的core链表,浅蓝色箭头表示单向循环的loop链表,红色箭头表示两次调用kmalloc
申请内存返回的内存地址
- 每个core的头
sizeof(header_t)
字节用来存放core_head节点信息,所以实际能用的内存比设置的min_core_size
整数倍要少 - 每次用
kmalloc
等接口申请内存时,实际申请出来的内存会比要求的内存大一点(具体见kmalloc代码第7行),这是为了在头sizeof(size_t)
字节存储该块的大小,方便以后kfree
的时候进行计算(kfree代码第7、8行就是把p
设置为这段内存真正的起始位置并获取大小)
API接口
初始化/销毁:km_init、km_destroy
申请
malloc:kmalloc系列
kmalloc:最核心的申请内存接口
申请步骤:
- km为空则直接
malloc
申请对应大小的内存 - 否则尝试从当前内存块链表中取满足大小的内存块出来
- 先计算申请的内存块大小相当于多少个unit:
n_units
- 循环loop链表,尝试找到一个满足目标大小的节点
p->size >= n_units
- 如果找得到且大小刚好符合,直接把该节点取出来,更新loop_head并返回
- 如果找得到且大小比较大,则把该节点的后半部分取出来,更新loop_head并返回
- 如果找不到,则需要调用morecore新增一个core,再从新的core部分取目标大小出来
- 先计算申请的内存块大小相当于多少个unit:
void *kmalloc(void *_km, size_t n_bytes) {kmem_t *km = (kmem_t*)_km;size_t n_units;header_t *p, *q;...if (km == NULL) return malloc(n_bytes);n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t); /* header+n_bytes requires at least this number of units */if (!(q = km->loop_head)) /* the first time when kmalloc() is called, intialize it */q = km->loop_head = km->base.ptr = &km->base;for (p = q->ptr;; q = p, p = p->ptr) { /* search for a suitable block */if (p->size >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */if (p->size == n_units) q->ptr = p->ptr; /* no need to split the block */else { /* split the block. NB: memory is allocated at the end of the block! */p->size -= n_units; /* reduce the size of the free block */p += p->size; /* p points to the allocated block */*(size_t*)p = n_units; /* set the size */}km->loop_head = q; /* set the end of chain */return (size_t*)p + 1;}if (p == km->loop_head) { /* then ask for more "cores" */if ((p = morecore(km, n_units)) == 0) return 0;}}
}
Kmalloc、KMALLOC:都是调用kmalloc
,一个指定类型,一个传入指针即可
#define Kmalloc(km, type, cnt) ((type*)kmalloc((km), (cnt) * sizeof(type)))
#define KMALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kmalloc((km), (len) * sizeof(*(ptr))))
新申请一个core
申请步骤:
- 计算目标大小占用unit数
nu
,换算到整数个min_core_size
上 - 从父结构那里申请对应大小的内存
bytes
(如果父结构为空则直接malloc
) - 把新core插入到core链表头部
- 调用kfree初始化新core,把它加入到loop链表中,并返回
loop_head
static header_t *morecore(kmem_t *km, size_t nu)
{header_t *q;size_t bytes, *p;nu = (nu + 1 + (km->min_core_size - 1)) / km->min_core_size * km->min_core_size; /* the first +1 for core header */bytes = nu * sizeof(header_t);q = (header_t*)kmalloc(km->par, bytes);if (!q) panic("[morecore] insufficient memory");q->ptr = km->core_head, q->size = nu, km->core_head = q;p = (size_t*)(q + 1);*p = nu - 1; /* the size of the free block; -1 because the first unit is used for the core header */kfree(km, p + 1); /* initialize the new "core"; NB: the core header is not looped. */return km->loop_head;
}
calloc:kcalloc系列
- kcalloc:根据情况选用
calloc
或kmalloc
- Kcalloc、KCALLOC:都是调用
kcalloc
void *kcalloc(void *_km, size_t count, size_t size) {...if (km == NULL) return calloc(count, size);p = kmalloc(km, count * size);memset(p, 0, count * size);return p;
}#define Kcalloc(km, type, cnt) ((type*)kcalloc((km), (cnt), sizeof(type)))
#define KCALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kcalloc((km), (len), sizeof(*(ptr))))
realloc:krealloc系列
- krealloc:根据情况选用
realloc
或kmalloc
。如果容量剩余空间比较大则直接返回,否则重新申请一块区域并拷贝数据,然后释放原位置 - Krealloc、KREALLOC:都是调用
krealloc
void *krealloc(void *_km, void *ap, size_t n_bytes) { // TODO: this can be made more efficient in principle...if (km == NULL) return realloc(ap, n_bytes);if (ap == NULL) return kmalloc(km, n_bytes);...if (cap >= n_bytes) return ap; /* TODO: this prevents shrinking */q = (size_t*)kmalloc(km, n_bytes);memcpy(q, ap, cap);kfree(km, ap);return q;
}#define Krealloc(km, type, ptr, cnt) ((type*)krealloc((km), (ptr), (cnt) * sizeof(type)))
#define KREALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))krealloc((km), (ptr), (len) * sizeof(*(ptr))))
krelocate
就是重新找块区域放置数据,可用于内存比较碎片化时整理内存
void *krelocate(void *km, void *ap, size_t n_bytes) {...p = kmalloc(km, n_bytes);memcpy(p, ap, n_bytes);kfree(km, ap);return p;
}
expand:Kexpand系列
调用krealloc
,按1.5倍的增长趋势扩大内存块
#define Kexpand(km, type, a, m) do { \(m) = (m) >= 4? (m) + ((m)>>1) : 16; \(a) = Krealloc(km, type, (a), (m)); \} while (0)#define KEXPAND(km, a, m) do { \(m) = (m) >= 4? (m) + ((m)>>1) : 16; \KREALLOC((km), (a), (m)); \} while (0)
释放:kfree
用于把一块“外部内存块”加入当前loop链表
释放过程:
- km为空则表示直接释放对应内存
p
指向要释放的内存块头信息的位置- 尝试找到应该插入的位置
q
,根据p
与q
的位置关系判断其情况,进行合并- 下面的注释中显示了五种情况,源代码中只有四种情况的图示(
p
与q
或q->ptr
相邻可以整合的),我加了第三种p
与两边都不相邻的图示
- 下面的注释中显示了五种情况,源代码中只有四种情况的图示(
void kfree(void *_km, void *ap) { /* kfree() also adds a new core to the circular list */...if (km == NULL) {free(ap);return;}p = (header_t*)((size_t*)ap - 1);p->size = *((size_t*)ap - 1);/* Find the pointer that points to the block to be freed. The following loop can stop on two conditions:** a) "p>q && p<q->ptr": @------#++++++++#+++++++@------- @---------------#+++++++@-------* (can also be in | | | => | |* two cores) q p q->ptr q q->ptr** @-------- #+++++++++@-------- @-------- @------------------* | | | => | |* q p q->ptr q q->ptr** @-----#++++++#++++++#++++@------ @-----#++++++@------#++++@------* | | | => | | |* q p q->ptr q q->ptr q->ptr->ptr** b) "q>=q->ptr && (p>q || p<q->ptr)": * @-------#+++++ @--------#+++++++ @-------#+++++ @----------------* | | | => | |* q->ptr q p q->ptr q** #+++++++@----- #++++++++@------- @------------- #++++++++@-------* | | | => | |* p q->ptr q q->ptr q*/for (q = km->loop_head; !(p > q && p < q->ptr); q = q->ptr)if (q >= q->ptr && (p > q || p < q->ptr)) break;if (p + p->size == q->ptr) { /* two adjacent blocks, merge p and q->ptr (the 2nd and 5th cases) */p->size += q->ptr->size;p->ptr = q->ptr->ptr;} else if (p + p->size > q->ptr && q->ptr >= p) { /* this should not happen */panic("[kfree] The end of the allocated block enters a free block.");} else p->ptr = q->ptr; /* backup q->ptr (the 3rd case) */if (q + q->size == p) { /* two adjacent blocks, merge q and p (the 1st and 4th cases) */q->size += p->size;q->ptr = p->ptr;km->loop_head = q;} else if (q + q->size > p && p >= q) { /* this should not happen */panic("[kfree] The end of a free block enters the allocated block.");} else km->loop_head = p, q->ptr = p; /* in two cores, cannot be merged; create a new block in the list */
内存池
数据结构主体
还记得klist模块的小内存池吗?这个跟那个是一样的,用数组模拟栈操作,就只是用上面的内存块管理模块替换了直接申请内存操作
#define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \typedef struct { \size_t cnt, n, max; \kmptype_t **buf; \void *km; \} kmp_##name##_t; ...#define KALLOC_POOL_INIT(name, kmptype_t) \KALLOC_POOL_INIT2(static inline klib_unused, name, kmptype_t)
kmp_##name##_t
:内存池结构cnt
:给外部使用的内存块个数n
:目前内存池中可用的内存块个数max
:内存池容量buf
:内存池km
:内存块管理结构体指针
KALLOC_POOL_INIT
:定义内存池宏name
:用户自定义名字(大小写字母下划线数字等)kmptype_t
:内存池管理的数据类型
初始化/销毁:kmp_init_name、kmp_destroy_name
申请/释放:kmp_alloc_name、kmp_free_name
kmp_alloc_##name
:没有可用的内存块就用kcalloc
申请,有则直接返回“栈顶”内存块(出栈)
kmp_free_##name
:内存池容量已满就用Kexpand
扩容,然后把内存块放到“栈顶”(入栈)
#define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \...\SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \++mp->cnt; \if (mp->n == 0) return (kmptype_t*)kcalloc(mp->km, 1, sizeof(kmptype_t)); \return mp->buf[--mp->n]; \} \SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \--mp->cnt; \if (mp->n == mp->max) Kexpand(mp->km, kmptype_t*, mp->buf, mp->max); \mp->buf[mp->n++] = p; \}
相关文章:
轻量级C通用库Klib解读 —— kalloc
前言 Klib是一个独立的轻量级c通用库,里面大多数组件除了C标准库外不包含外部库,想用对应组件直接拷贝对应文件即可使用。 该库致力于高效和较小的内存占用,其中部分组件(如khash、kbtree、ksort、kvec),无…...
认识HTML的标签结构
一、HTML的基本概念 1.什么是HTML? ①HTML是描述网页的一种标记语言,也被称为超文本标记语言【并不是一种编程语言】 ②HTML包含了HTML标签和文本内容 ③HTML文档也称为web页面 2.HTML的标签 HTML的标签通常成对出现,HTML文档由标签和受…...
C语言 实现一个比较两个整型的函数 / qsort的使用 /qsort排序结构体
一、qsort的一般使用方法 int cmp_int(const void* e1, const void* e2) {return *(int*)e1 - *(int*)e2; } // //使用qsort对数组进行排序,升序 void test1() {int arr[] { 9,8,7,6,5,4,3,2,1,0 };int sz sizeof(arr) / sizeof(arr[0]);//bubble_sort(arr, sz);…...
Arcmap python环境安装sklearn
Arcmap自带的环境为Python2.7,默认安装目录为C:\Python27\ArcGIS10.7 直接安装sklearn会发生兼容性问题,且默认环境不包括pip,因此需要先安装pip 下载 get-pip.py 访问 https://bootstrap.pypa.io/pip/2.7/get-pip.py 并下载 get-pip.py。运…...
FastAdmin后端列表导入表格数据
后台添加数据的时候增加通过表格导入功能 如下图index.html页面增加导入和模板下载按钮代码如下 <div class"panel panel-default panel-intro">{:build_heading()}<div class"panel-body"><div id"myTabContent" class"ta…...
R语言用逻辑回归贝叶斯层次对本垒打数据与心脏移植数据后验预测检验模拟推断及先验影响分析|附数据代码...
全文链接:https://tecdat.cn/?p40152 在统计学领域中,层次建模是一种极为强大且实用的工具。它能够巧妙地处理复杂的数据结构,通过分层的方式对数据进行建模。在贝叶斯统计的框架内,层次建模优势尽显,其可以有效地融合…...
Python基于自然语言处理技术的新闻文本分类系统【附源码、文档说明】
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
mybatis存储过程返回list
在MyBatis中调用存储过程并返回列表(List)通常涉及以下几个步骤: 定义存储过程:首先,在数据库中定义存储过程,并确保它返回结果集。配置MyBatis映射文件:在MyBatis的映射文件中配置调用存储过程…...
Unity项目实战-订阅者发布者模式
实战订阅者发布者模式详解 下面实例是一个射击类游戏,玩家可以切换枪支,最初的设计如下 public class Player:MonoBehaviour {//......省略代码逻辑//我们以及配置好了Scroll的输入,并配置了Scroll的输入事件,当玩家滚动鼠标滚轮…...
长文档处理痛点:GPT-4 Turbo引文提取优化策略与替代方案讨论
引言 随着GPT-4 Turbo的发布,其支持的128K上下文窗口(约300页文本)被视为处理长文本的突破性升级。然而,实际应用中,用户发现模型在提取长文档中的引文时存在显著缺陷:文档前三分之一的引文数量远多于中间…...
Deepseek 万能提问公式:高效获取精准答案
### **Deepseek 万能提问公式:高效获取精准答案** 在使用 Deepseek 或其他 AI 工具时,提问的质量直接决定了答案的精准度和实用性。以下是一个万能的提问公式回答: --- ### **1. 明确背景(Context)** - **作用**…...
Ubuntu中离线安装Docker
Ubuntu中离线安装Docker 前言 本教程将详细介绍如何在 Ubuntu 22.04 系统上,通过 .deb 包离线安装 Docker CE、Docker CE CLI 和 Docker Compose。 适用于无法访问互联网的环境。 准备工作 下载 .deb 包 在可以访问互联网的机器上,下载 Docker CE、…...
Linux配置SSH公钥认证与Jenkins远程登录进行自动发布
问题描述:在使用jenkins进行自动化部署时,其中一步是使用jenkins向目标服务器推送文件时,需要先在jenkins的系统配置中进行配置(事先安装好对应插件),配置远程服务器时,报错: 检查以…...
【故障处理】- 11g数据泵到19c导致的job不自动执行
【故障处理】- 11g数据泵到19c导致的job不自动执行 一、概述二、报错原因三、解决方法 一、概述 业务正常上线以后,客户反馈大量的job到时间了也不正常运行。 二、报错原因 该报错匹配bug 32249704,导致了迁移之后job的log_user从业务用户变成了sys。JOB…...
WPF8-常用控件
目录 写在前面:1. 按钮控件1.1. Button 按钮1.2. RepeatButton:长按按钮1.3. RadioButton:单选按钮 2. 数据显示控件2.1. TextBlock:只读文本控件2.2. Lable:标签 显示文本控件2.3. ListBox:显示可选择项的列表2.4. DataGrid&…...
电商小程序(源码+文档+部署+讲解)
引言 随着移动互联网的快速发展,电商小程序成为连接消费者与商家的重要桥梁。电商小程序通过数字化手段,为消费者提供了一个便捷、高效的购物平台,从而提升购物体验和满意度。 系统概述 电商小程序采用前后端分离的架构设计,服…...
关于C#的一些基础知识点汇总
1.C#结构体可以继承接口吗?会不会产生GC? 在 C# 中,结构体不能继承类,但可以实现接口。 代码: interface IMyInterface {void MyMethod(); }struct MyStruct : IMyInterface {public void MyMethod(){Console.Write…...
七、敏捷开发工具:持续集成与部署工具
一、敏捷开发工具——持续集成与部署工具 持续集成(CI)与持续部署(CD)是现代敏捷开发中不可或缺的关键实践。通过自动化构建、测试和部署流程,团队可以快速反馈、提高代码质量,并加速产品交付。为此,持续集成与部署工具应运而生,它们能够帮助开发团队在整个开发周期内…...
【工具类】 Hutool 中用于生成随机数的工具类
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
vue3和vue2的组件开发有什么区别
Vue3和Vue2在组件开发上存在不少差异,下面从多个方面详细介绍: 响应式原理 Vue2:用Object.defineProperty()方法来实现响应式。打个比方,它就像给对象的每个属性都安排了一个“小管家”,属性被访问或修改时࿰…...
防御保护选路练习
拓扑 配置 IP的基本配置 r2 [R2]int g0/0/0 [R2-GigabitEthernet0/0/0]ip add 12.0.0.2 255.255.255.0 [R2]int g0/0/2 [R2-GigabitEthernet0/0/2]ip add 210.1.1.254 255.255.255.0 [R2-GigabitEthernet0/0/2]int g0/0/1 [R2-GigabitEthernet0/0/1]ip add 200.1.1.254 255.…...
SQL Server 运算符优先级
在 SQL Server 中,运算符的优先级决定了在没有使用括号明确指定计算顺序时,运算符的执行顺序。 运算符优先级列表 括号 () 一元运算符 (正号)-(负号)~(按位取反) 乘法、除法和取模…...
【RK3588嵌入式图形编程】-SDL2-构建模块化UI
构建模块化UI 文章目录 构建模块化UI1、概述2、创建UI管理器3、嵌套组件4、继承5、多态子组件6、总结在本文中,将介绍如何使用C++和SDL创建一个灵活且可扩展的UI系统,重点关注组件层次结构和多态性。 1、概述 在前面的文章中,我们介绍了应用程序循环和事件循环,这为我们的…...
用STC-ISP写延时函数
若想写出自己可以定义时长的延时函数,需要重新生成一个1ms的延时函数并稍加修改。 STC-ISP生成的1ms的延时函数代码如下: void Delay1ms(void) //12.000MHz {unsigned char data i, j;i 2;j 239;do{while (--j);} while (--i); }将上述代码改为可自定…...
DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
对于个人开发者或尝鲜者而言,本地想要部署 DeepSeek 有很多种方案,但是一旦涉及到企业级部署,则步骤将会繁琐很多。 比如我们的第一步就需要先根据实际业务场景评估出我们到底需要部署什么规格的模型,以及我们所要部署的模型&…...
使用 Docker 部署 Apache Spark 集群教程
简介 Apache Spark 是一个强大的统一分析引擎,用于大规模数据处理。本文将详细介绍如何使用 Docker 和 Docker Compose 快速部署一个包含一个 Master 节点和两个 Worker 节点的 Spark 集群。这种方法不仅简化了集群的搭建过程,还提供了资源隔离、易于扩…...
基于暗通道先验的图像去雾算法解析与实现
一、算法背景 何凯明团队于2009年提出的暗通道先验去雾算法《single image haze removal using dark channel prior》,通过统计发现:在无雾图像的局部区域中,至少存在一个颜色通道的像素值趋近于零。这一发现为图像去雾提供了重要的理论依据…...
深入内存调试:Valgrind工具的终极指南(转)
在软件开发的世界里,代码质量就是生命线,而内存管理又是这条生命线中最脆弱的一环。内存泄漏,哪怕只是微小的一处,日积月累,都可能对整个系统造成灾难性的打击,无论是大型企业级应用、实时性要求极高的嵌入…...
深入解析MediaPipe:强大的实时计算机视觉框架
深入解析MediaPipe:强大的实时计算机视觉框架 1. 引言 在计算机视觉应用的快速发展中,实时处理和低延迟成为了许多应用的关键需求。Google 开发的 MediaPipe 是一个强大的开源框架,它能够高效处理 手势识别、姿态估计、物体检测、语音处理 …...
DeepSeek 和 ChatGPT 在特定任务中的表现:逻辑推理与创意生成
🎁个人主页:我们的五年 🔍系列专栏:Linux网络编程 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 Linux网络编程笔记: https://blog.cs…...
大白话实战Sentinel
Sentinel是SpringCloudAlibaba提供的用来做服务保护的框架,而服务保护的常见手段就是限流和熔断降级。在大型分布式系统里面,由于微服务众多,所以服务之间的稳定性需要做特别关注,Sentinel的核心包就提供了从多个维度去保护服务稳定的策略,而且这些保护策略都可以连接上Se…...
【AI面板识别】
题目描述 AI识别到面板上有N(1 ≤ N ≤ 100)个指示灯,灯大小一样,任意两个之间无重叠。 由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1&#x…...
Docker安装Kafka(不依赖ZooKeeper)
创建docker-compose.yaml version: "3.9" #版本号 services:kafka:image: apache/kafka:3.9.0container_name: kafkahostname: kafkaports:- 9092:9092 # 容器内部之间使用的监听端口- 9094:9094 # 容器外部访问监听端口environment:KAFKA_NODE_ID: 1KAFKA_PROCES…...
大道至简 少字全意 易经的方式看 jvm基础 、 内存模型 、 gc、 内存异常、内存调优实战案例 、类加载机制、双亲委派模型 适用于 懂而久未用回忆 ,不懂而需明正理而用
目录 介绍 内存模型 一、线程私有区域 二、线程共享区域 1.堆Heap 2. 方法区Method Area 3.运行时常量池 Runtime constant Pool 三、直接内存(Direct Memory) 四、内存异常与调优 五、总结对比 类加载机制 一、类加载的三大阶段 二、双亲委派模型 三、类加载的特…...
【Java学习】继承
一、继承 子类继承父类,子类这个类变量的引用在原有的指向子类自己类变量空间的原有访问权限上,增加上了父类类变量空间的访问权限,此时子类类变量指向的空间变为了原来子类类变量空间加上父类类变量空间,此时子类类变量空间就变成…...
Ubuntu24安装MongoDB(解压版)
目录 0.需求说明1.环境检查2.下载软件2.1.下载MongoDB服务端2.2.下载MongoDB连接工具(可略过)2.3.检查上传或下载的安装包 3.安装MongoDB3.1.编辑系统服务3.2.启动服务3.3.客户端连接验证3.3.1.创建管理员用户 4.远程访问4.1.开启远程访问4.2.开放防火墙 0.需求说明 问&#x…...
计算机毕业设计Python考研院校推荐系统 考研分数线预测 考研推荐系统 考研可视化(代码+LW文档+PPT+讲解视频)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
Python 爬虫框架对比与推荐
Python 爬虫框架对比与推荐 Python 爬虫框架对比与推荐1. Scrapy1.1 框架介绍1.2 优点1.3 缺点1.4 适用场景 2. PySpider2.1 框架介绍2.2 优点2.3 缺点2.4 适用场景 3. Selenium3.1 框架介绍3.2 优点3.3 缺点3.4 适用场景 4. BeautifulSoup Requests(自定义方案&am…...
本地DeepSeek模型GGUF文件转换为PyTorch格式
接前文,我们在本地Windows系统上,基于GGUF文件部署了DeepSeek模型(DeepSeek-R1-Distill-Qwen-1.5B.gguf版本),但是GGUF是已经量化的版本,我们除了对其进行微调之外,无法对其训练,那么还有没有其他办法对本地的GGUF部署的DeepSeek模型进行训练呢?今天我们就反其道而行之…...
自动化测试框架搭建-单次接口执行-三部曲
目的 判断接口返回值和提前设置的预期是否一致,从而判断本次测试是否通过 代码步骤设计 第一步:前端调用后端已经写好的POST接口,并传递参数 第二步:后端接收到参数,组装并请求指定接口,保存返回 第三…...
SAP F1搜索帮助 添加自定义功能按钮
最近deepseek 比较火,好多伙伴把deep seek 调用集成到SAP 系统,集成需要方便的去查询问题,方便一点就是添加在F1搜索帮助的地方,看到有朋友问看自定义按钮怎么添加在F1的工具栏,跟踪了下代码,尝试了下&…...
Webpack,Vite打包的理解
Webpack 和 Vite 都是现代前端开发中常用的构建工具,用于打包和优化项目代码。尽管它们的目标相似,但在设计理念、工作方式和适用场景上存在显著差异。 Webpack Webpack 是一个模块打包工具,主要用于将多个模块(如 JavaScript、…...
ollama部署大模型,本地调用
Ollama是一个强大的大型语言模型平台,它允许用户轻松地下载、安装和运行各种大型语言模型。在本文中,我将指导你如何在你的本地机器上部署Ollama,并展示如何使用Python进行简单的API调用以访问这些模型。 最近很多人在学习大模型的时候&…...
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑩】
ISO 14229-1:2023 UDS诊断【ECU复位0x11服务】_TestCase10 作者:车端域控测试工程师 更新日期:2025年02月18日 关键词:UDS诊断协议、ECU复位服务、0x11服务、ISO 14229-1:2023 TC11-010测试用例 用例ID测试场景验证要点参考条款预期结果TC…...
opencv实时二维码识别的一种实现与思路分享
在嵌入式平台上比如 rk3568 这种弱鸡的平台,要做到实时视频处理就非常鸡肋,不像英伟达那种 deepstrem 什么的。 开始的时候,我们使用python 下的 pyzbar + opencv opencv 读取摄像头的数据然后每帧送到 pyzbar 二维码识别函数里面进行处理,然后打印出识别的数字。结果,非常…...
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑫】
ISO 14229-1:2023 UDS诊断【ECU复位0x11服务】_TestCase12 作者:车端域控测试工程师 更新日期:2025年02月18日 关键词:UDS诊断协议、ECU复位服务、0x11服务、ISO 14229-1:2023 TC11-012测试用例 用例ID测试场景验证要点参考条款预期结果TC…...
Jenkins同一个项目不同分支指定不同JAVA环境
背景 一些系统应用,会为了适配不同的平台,导致不同的分支下用的是不同的gradle,导致需要不同的JAVA环境来编译,比如a分支需要使用JAVA11, b分支使用JAVA17。 但是jenkins上,一般都是Global Tool Configuration 全局所有环境公用一个JAVA_HOME。 尝试过用 Build 的Execut…...
小爱音箱连接电脑外放之后,浏览器网页视频暂停播放后,音箱整体没声音问题解决
背景 22年买的小爱音箱增强版play,小爱音箱连接电脑外放之后,浏览器网页视频暂停播放后,音箱整体没声音(一边打着游戏,一边听歌,一边放视频,视频一暂停,什么声音都没了,…...
AIGC(生成式AI)试用 21 -- Python调用deepseek API
1. 安装openai pip3 install openai########################## Collecting openaiUsing cached openai-1.61.1-py3-none-any.whl.metadata (27 kB) Collecting anyio<5,>3.5.0 (from openai)Using cached anyio-4.8.0-py3-none-any.whl.metadata (4.6 kB) Collecting d…...
使用linux脚本部署discuz博客(详细注释版)
使用脚本部署一个discuzz项目 1.显示当前环境状态 防火墙状态 selinux状态 httpd状态 由上可知,虚拟机已处于最初始状态 2.脚本编写 #!/bin/bash #这是一个通过脚本来部署discuzz博客 firewalld关闭 systemctl stop firewalld if [ $? -eq 0 ];then echo "…...