slab 缓存以及slabtop 命令学习

一、slab 缓存介绍

1.1、什么是slab 缓存

SLAB缓存是Linux内核中用于优化内存分配和管理的一种机制,特别针对频繁分配和释放的固定大小的小对象。它是基于 通用内存分配器(如伙伴系统) 之上的一个中间层,旨在通过减少分配和释放小对象的开销、降低内存碎片以及提高缓存局部性来提升系统性能。SLAB缓存的核心思想是 在内核中预先分配一系列相同大小的对象,并将这些对象组织成称为"SLAB"的连续内存块,从而实现高效的内存重用。

1.2、slab 缓存原理

slab 缓存原理如下:

  • 初始化阶段:当内核首次需要分配特定类型和大小的对象时,SLAB分配器会从伙伴系统中分配一大块连续内存(远大于单个对象的需求),并将这块内存切割成多个相同大小的槽位(slot),每个槽位用来存放一个对象。这些槽位组成的集合称为一个SLAB。

  • 对象缓存:每个SLAB都属于一个特定类型的缓存(cache),缓存定义了对象的大小、初始化函数(如果需要的话)以及其他属性。内核维护了一个全局的缓存列表,便于快速查找和分配对象。

  • 分配与释放:当需要一个新的对象时,SLAB分配器首先尝试从已有的、含有未分配对象的SLAB中分配。如果找不到合适的SLAB,才会从伙伴系统中分配新的内存块并创建新的SLAB。释放对象时,通常并不立即归还给伙伴系统,而是留在SLAB中作为未使用的对象,以便下次快速重用,减少了内存碎片和分配开销。

  • 缓存策略:SLAB缓存支持多种策略来管理对象,包括SLAB的分裂与合并、缓存的收缩与扩张、以及冷热数据分离等,以适应不同的使用场景和性能要求。

1.3、slab 缓存优势

  • 减少分配和释放的开销:通过重用对象,避免了每次分配和释放时的系统调用和内存管理开销。
  • 减少内存碎片:通过预分配和固定大小的策略,减少了外部碎片问题。
  • 提高缓存局部性:由于对象在物理内存中是连续存放的,可以提高CPU缓存的命中率。
  • 优化性能:特别是对于频繁操作的小对象,如文件描述符、网络套接字等,可以显著提高系统整体性能。

1.4、slab 的发展

随着时间的发展,SLAB缓存也在不断进化,引入了更高级的管理策略,例如SLOB(Simple List of Blocks,适用于嵌入式系统)和SLUB(SLAB Unqueued,优化了锁的使用,提高了多核处理器的性能)

二、slab 核心概念

2.1、 slab状态

Slab是SLAB机制中的基本组成单元,它是预先分配的一块连续的内存区域。每个Slab由一个或多个大小相同的对象组成,这些对象属于同一个Cache。Slab可以处于以下几种状态之中:

  • Partial(部分分配): 这是最常见的状态。当一个SLAB被分配并开始使用时,最初它可能只有部分对象被分配出去,而其他对象仍处于未分配状态。此时,SLAB处于“部分分配”状态。随着对象的分配和释放,SLAB中的对象数量会变化,但只要还有至少一个对象未被使用,SLAB就保持在这个状态。

  • Full(全分配): 当SLAB中的所有对象都被分配出去,没有剩余未分配对象时,该SLAB就进入了“全分配”状态。这意味着如果有新的分配请求,内核必须寻找其他SLAB或创建新的SLAB来满足需求,而不能直接从这个SLAB中分配。

  • Empty(空闲): 当SLAB中的所有对象都被释放,没有活跃对象时,理论上可以认为SLAB进入了一个“空闲”状态。然而,在实际的SLAB管理中,空闲的SLAB并不直接返回给伙伴系统,而是保持在缓存中以便快速重用。因此,严格来说,Linux SLAB分配器中并没有一个明确标记为“Empty”的状态,但它可以通过“部分分配”状态且所有对象都是未分配的状态来近似理解。

  • Freeing(释放中): 当SLAB决定被销毁或归还给伙伴系统时,它会进入释放流程,这可能包括清除对象数据、执行必要的清理操作等。

  • Reclaim(回收): 在某些情况下,SLAB可能会被标记为可回收状态,等待内核的内存回收机制处理,这通常发生在内存压力较大时。

2.2、slab cache

SLAB Cache,全称SLAB分配器缓存,是Linux内核中一种高效的内存管理机制,专门设计用于优化对小而频繁分配和释放的内核对象的处理。SLAB缓存通过预先分配和管理一组相同大小的对象,极大地减少了内存分配和释放的开销,同时降低了内存碎片,提高了系统性能。下面是对SLAB Cache的详细介绍:

  • 目的:解决传统内存分配器(如伙伴系统)在处理小对象时的效率低下问题,减少内存碎片,加快对象分配和释放速度。

  • 原理:SLAB将物理内存分割成多个缓存区(Cache),每个Cache对应一类特定大小和类型的内核对象。每个Cache又由多个SLAB组成,每个SLAB是一块连续内存,被划分为多个固定大小的槽位(Slots),每个槽位用于存放一个对象实例。

  • 对象池化:预先分配大量相同类型和大小的对象,形成对象池,当需要时直接从池中分配,释放时回收至池中而非归还给底层内存管理系统,减少了分配和释放的系统开销。

  • 缓存层次:SLAB之上有多个层次的缓存管理,包括per-CPU缓存、全局缓存等,进一步加速了对象的分配和回收过程。

  • 对象初始化:支持对象构造和析构回调,可以在对象分配和释放时执行特定的初始化和清理操作,保持对象的一致性。

  • 内存回收策略:SLAB在内存紧张时可以释放未使用的SLAB,或者在长时间未使用的SLAB上执行内存回收,以应对系统对内存的动态需求。

  • 多态性:支持多种SLAB分配策略,如SLAB、SLUB(SLAB Unqueued,减少了锁的使用,提高了多处理器系统的性能)和SLOB(Simple List of Blocks,用于资源受限环境)

2.3、缓存色彩(Cache Coloring)

Cache Coloring技术主要是为了解决多核处理器系统中的一种现象——伪共享(False Sharing)。伪共享发生在两个或多个处理器核心访问同一缓存行(Cache Line)的不同变量时,即使这些变量逻辑上无关。由于缓存一致性协议,当一个核心修改了该缓存行的一个变量,其他核心即使只读取该行的其他变量,整个缓存行也需要在各个核心之间同步,导致不必要的性能损失。

着色策略:

  • 物理着色:在分配内存时,确保相关数据跨不同缓存行分布,避免伪共享。这通常需要操作系统或编译器的支持,通过对齐数据结构到缓存行边界或使用特定的内存分配函数来实现。
  • 逻辑着色:软件层面的解决方案,通过编程技巧(比如padding)人为增加数据结构大小,确保相邻变量位于不同的缓存行。

2.4 构造器和析构器

构造器(Constructor)
构造器是在对象被分配给用户之前调用的函数。它的主要职责是初始化新分配对象的数据成员,确保对象处于一个有效的、可用的状态。对于内核对象而言,这可能涉及到设置默认值、配置内部指针、初始化锁或其他同步原语等。构造器的使用使得每个新分配的对象都以一致的状态开始其生命周期,这对于维持系统稳定性至关重要。

析构器(Destructor)
析构器是在对象被释放回SLAB缓存之前调用的函数。它负责清理对象占用的任何资源,还原对象到一个干净的状态,准备下一次分配重用。这可能包括释放分配给对象的额外资源(如内存、文件描述符等)、重置状态标志、解除引用计数等操作。通过确保每个对象在被重新分配前都被正确清理,析构器有助于防止内存泄漏和资源耗尽问题。

如何使用
在内核编程中,构造器和析构器通常在定义SLAB缓存时指定。例如,使用kmem_cache_create()函数创建一个新的SLAB缓存时,可以传入构造器和析构器的函数指针作为参数。这样,每次从该缓存中分配或释放对象时,相应的构造器和析构器就会自动被调用。

实例

struct my_obj {/* 成员变量定义 */
};static void my_obj_constructor(void *objp, kmem_cache_t *cachep, unsigned long flags)
{struct my_obj *obj = objp;/* 初始化obj的成员变量 */
}static void my_obj_destructor(void *objp)
{struct my_obj *obj = objp;/* 清理或重置obj的资源和状态 */
}/* 创建SLAB缓存 */
kmem_cache_t *my_cache = kmem_cache_create("my_cache",sizeof(struct my_obj),0,SLAB_PANIC,my_obj_constructor,NULL,my_obj_destructor);/* 之后就可以使用my_cache来分配和释放对象了 */
struct my_obj *new_obj = kmem_cache_alloc(my_cache, GFP_KERNEL);
/* 使用new_obj */
kmem_cache_free(my_cache, new_obj);

2.5、slab 缓存对象分配和释放过程

对象分配过程
对象的分配过程是SLAB机制的核心,旨在快速有效地提供所需的内存空间。以下是对象分配的基本步骤:

  • 查找合适的Slab Cache:当系统需要一个特定类型的对象时,首先在对应的Slab Cache中查找。
  • 选择Slab:在找到的Slab Cache中,系统会寻找状态为部分满(Partial)或空(Empty)的Slab。优先选择部分满的Slab,以提高内存利用率。
  • 分配对象:从选定的Slab中分配一个空闲对象。如果选择的是空Slab,系统会先初始化该Slab,然后分配对象。
  • 更新Slab状态:分配对象后,更新Slab的状态。如果所有对象都被分配,Slab状态变为满(Full)。

对象释放过程
与对象分配同样重要的是对象的释放过程,它确保了内存资源的有效回收和重用。对象释放过程包括以下步骤:

  • 确定对象所属的Slab:释放对象时,系统首先确定该对象属于哪个Slab。
  • 释放对象:将对象标记为未使用,返回到Slab的空闲对象池中。
  • 更新Slab状态:如果释放对象前Slab是满的,则释放后状态变为部分满(Partial)。如果释放后Slab中所有对象都是空闲的,则状态变为空(Empty)。
  • Slab的回收:如果一个Slab长时间处于空状态,系统可能会决定回收该Slab,释放内存给操作系统。

三、slab 监控

3.1、slabtop 命令

命令执行结果如下

 Active / Total Objects (% used)    : 6772985 / 6790551 (99.7%)Active / Total Slabs (% used)      : 162301 / 162301 (100.0%)Active / Total Caches (% used)     : 84 / 112 (75.0%)Active / Total Size (% used)       : 1218639.77K / 1225341.38K (99.5%)Minimum / Average / Maximum Object : 0.01K / 0.18K / 15.25KOBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
3866811 3862386  99%    0.10K  99149	   39    396596K buffer_head
890946 890833  99%    0.19K  21213	 42    169704K dentry
664122 662990  99%    0.04K   6511	102     26044K ext4_extent_status
358400 358254  99%    1.00K  11200	 32    358400K ext4_inode_cache
279650 279650 100%    0.05K   3290	 85     13160K shared_policy_node
155072 153885  99%    0.06K   2423	 64	 9692K kmalloc-64
153916 153332  99%    0.57K   5497	 28     87952K radix_tree_node78168  73411  93%    0.66K   3257	 24     52112K proc_inode_cache68568  68315  99%    0.66K   2857	 24     45712K ovl_inode31552  31466  99%    0.12K    928	 34	 3712K kernfs_node_cache26381  26381 100%    0.21K    713	 37	 5704K vm_area_struct19698  19698 100%    0.09K    469	 42	 1876K kmalloc-9616416  16416 100%    0.58K    608	 27	 9728K inode_cache14280  14280 100%    0.04K    140	102	  560K selinux_inode_security14127  13465  95%    0.08K    277	 51	 1108K anon_vma13312  12471  93%    0.03K    104	128	  416K kmalloc-3211776  11776 100%    0.01K     23	512        92K kmalloc-811520  10895  94%    0.12K    360	 32	 1440K kmalloc-1289472   9472 100%    0.02K     37	256	  148K kmalloc-169450   9133  96%    0.19K    225	 42	 1800K kmalloc-1928480   7431  87%    0.25K    265	 32	 2120K kmalloc-2567808   7808 100%    0.03K     61	128	  244K jbd2_revoke_record_s6300   6300 100%    0.19K    150	 42	 1200K cred_jar4352   4352 100%    0.06K     68	 64	  272K ext4_free_data4312   4312 100%    0.07K     77	 56	  308K avc_node4020   4020 100%    0.13K    134	 30	  536K ext4_groupinfo_4k4000   3739  93%    1.00K    125	 32	 4000K kmalloc-10243488   3242  92%    0.50K    109	 32	 1744K kmalloc-5123024   3024 100%    0.38K     72	 42	 1152K mnt_cache3024   3024 100%    0.11K     84	 36	  336K jbd2_journal_head2904   2853  98%    0.66K    121	 24	 1936K shmem_inode_cache2825   2825 100%    0.62K    113	 25	 1808K sock_inode_cache2720   2720 100%    0.02K     16	170        64K fsnotify_mark_connector2675   2675 100%    0.31K    107	 25	  856K nf_conntrack_1

命令结果解析

  • Active / Total Objects (% used):
    • Active Objects: 当前正在被使用的对象数量(即已分配出去的对象)。
    • Total Objects: SLAB缓存中所有对象的总容量。
    • (99.7%): 当前活跃对象占总对象容量的百分比。在这个例子中,约99.7%的SLAB对象已被分配使用,表明SLAB缓存的使用率非常高,接近饱和。
  • Active / Total Slabs (% used):
    • Active Slabs: 正在使用中的SLAB数量,即包含至少一个活跃对象的SLAB。
    • Total Slabs: 总共创建的SLAB数量。
    • (100.0%): 所有SLAB都在使用中,说明没有空闲的SLAB,SLAB资源完全被占用。
  • Active / Total Caches (% used):
    • Active Caches: 当前活跃的SLAB缓存数量,即至少有一个活跃对象的缓存。
    • Total Caches: 系统中定义的所有SLAB缓存的数量。
    • (75.0%): 表示活跃的SLAB缓存占总缓存数量的比例,这里75%的缓存正在被使用,剩余25%可能是未被访问或暂时不需要的缓存。
  • Active / Total Size (% used):
    • Active Size: 当前被活跃对象占用的总内存大小。
    • Total Size: SLAB缓存分配的总内存大小。
    • (99.5%): 活跃对象占用的内存比例,表明SLAB缓存中的内存使用率极高。
  • Minimum / Average / Maximum Object:
    • Minimum Object: SLAB缓存中对象的最小尺寸,这里是0.01K,即10字节。
    • Average Object: SLAB缓存中对象的平均尺寸,这里是0.18K,即180字节。
    • Maximum Object: SLAB缓存中对象的最大尺寸,这里是15.25K,即15250字节。

buffer_head缓存为例,slabtop获取到的缓存字段含义如下:

字段解释
OBJS总对象数量,对于buffer_head缓存来说,共有3,866,811个对象。
ACTIVE活跃对象数量,此处有3,862,386个buffer_head对象正在被使用。
USE OBJ SIZE对象使用率,99%,意味着几乎所有的buffer_head对象都已被分配。
OBJ SIZE单个对象的大小,这里是0.10K,即每个buffer_head对象占用100字节。
SLABS总SLAB数量,共有99,149个SLAB用于存储buffer_head对象。
OBJ/SLAB每个SLAB中的对象数量,平均每个SLAB含有大约39个buffer_head对象。
CACHE SIZESLAB缓存的总大小,为396,596K(约等于396.6MB),这是所有buffer_head SLAB加起来占用的总内存。
NAME缓存名称,这里是buffer_head,与Linux内核中的缓冲头结构相关,常用于文件系统I/O操作。

常见缓存名称含义

缓存名称含义
buffer_head与文件系统操作相关,用于描述缓冲区头部信息,存储文件I/O操作中的元数据。
dentry目录项(Directory Entry)缓存,加速文件路径名查找。每个dentry对象代表文件系统中的一个目录项或文件名。
inode_cache索引节点(Inode)缓存,Inode包含文件的元数据信息,如权限、所有权、大小、时间戳等。高效的inode缓存对文件操作速度至关重要。
kmalloc通用的内核内存分配缓存,用于动态分配大小固定的内核内存块。
filp文件描述符(File Descriptor)缓存,每个filp对象对应一个打开的文件。
sock_inode_cache套接字inode缓存,用于网络连接相关的数据结构。
task_struct进程描述符缓存,每个运行的进程或线程都有一个对应的task_struct结构体。
skbuffSocket Buffer,网络数据包的缓存,用于网络数据的接收和发送。
vm_area_struct虚拟内存区域(VM Area)结构缓存,用于管理进程地址空间中的不同区域,如堆、栈、共享库映射等。
radix_tree_node前面提到过,与基数树数据结构相关,用于高效内存管理和查找。
fsnotify_mark_connector文件系统通知标记连接器,与FSNOTIFY机制相关,用于跟踪文件系统事件。
kmem_cache内核内存缓存自身的缓存,用于管理其他SLAB缓存的元数据。

3.2、/proc/slabinfo 文件

proc/slabinfo 是Linux系统中一个虚拟文件,提供了关于系统中SLAB缓存的详细信息。/proc/slabinfo 文件的内容可以在不使用额外工具的情况下直接查看,也可以通过像slabtop这样的工具进行更友好的展示和分析。示例如下:

cat /proc/slabinfo 
slabinfo - version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
ovl_inode          68315  68568    680   24    4 : tunables    0    0    0 : 
jbd2_journal_handle   1360   1360     48   85    1 : tunables    0    0    0 : slabdata     16     16      0
jbd2_journal_head   3024   3024    112   36    1 : tunables    0    0    0 : slabdata     84     84      0
jbd2_revoke_table_s    256    256     16  256    1 : tunables    0    0    0 : slabdata      1      1      0
jbd2_revoke_record_s   7808   7808     32  128    1 : tunables    0    0    0 : slabdata     61     61      0
...

包含字段含义如下

字段解释备注
nameSLAB缓存的名称,表明了该缓存类型,如kmalloc-64, dentry等,代表了内核中特定类型的对象。
active_objs活跃对象的数量,即当前正在被使用的对象数量。
num_objs缓存中对象的总数量,包括活跃和非活跃(未分配)的对象。
objsize单个对象的大小,单位通常是字节。
objperslab每个SLAB中包含的对象数量。
pagesperslab构成一个SLAB所需的物理页数,反映了SLAB的大小与页框(通常为4KB)的关系。
limit缓存自动扩展或收缩的上限值,决定了何时开始创建或销毁SLAB。SLAB缓存的调整参数(tunables)
batchcount在进行SLAB分配或回收时,每次操作的对象数量。SLAB缓存的调整参数(tunables)
sharedfactor如果是per-CPU SLAB,这个值表示每个CPU应该共享多少个SLAB;对于非per-CPU SLAB,这个值无意义。SLAB缓存的调整参数(tunables)
active_slabs当前活动的SLAB数量,即正在使用的SLAB。SLAB分配状态
num_slabs总SLAB数量,包括活动和非活动的。SLAB分配状态
sharedavail对于per-CPU SLAB,表示可用的共享SLAB数量;如果不是per-CPU SLAB,则这个字段可能没有意义或者显示为N/A。SLAB分配状态

参考文档

1、https://www.cnblogs.com/tcindex/p/16040808.html
2、https://zhuanlan.zhihu.com/p/491500340
3、https://developer.aliyun.com/article/1469092
4、https://kernel.meizu.com/2016/05/09/slab-allocator-and-kmalloc.html/
5、https://cloud.tencent.com/developer/article/2357041

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

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

相关文章

【数字图像处理】第5章 图像空域增强方法

上理考研周导师的哔哩哔哩频道 我在频道里讲课哦 目录 5.1 图像噪声 相关概念 ①图像噪声的产生 ② 图像噪声分类 ③ 图像噪声特点 5.2 图像增强方法分类 ①图像增强概念 ②图像增强目的 ③图像增强技术方法: 5.3 基于灰度变换的图像增强 1. 概述: 2. 灰度变换…

十大云手机排行榜:哪个云手机更好用?

近些年&#xff0c;市场上涌现出许多云手机产品&#xff0c;不同产品适合的应用场景也各不相同。在选用云手机之前&#xff0c;企业和个人用户需要了解它们的功能、特点以及适用的场景。本文将对当前主流的云手机进行对比&#xff0c;帮助大家挑选出最适合的云手机产品。 1. 红…

【数据结构与算法】之链表详解

链表是一种常用的数据结构&#xff0c;它是一种线性数据结构&#xff0c;但与数组不同&#xff0c;它并非连续存储数据&#xff0c;而是通过指针将数据节点连接起来。每个节点都包含数据域和指向下一个节点的指针域。这种结构赋予链表独特的优势和局限性&#xff0c;使其在某些…

九种排序,一次满足

我们在算法题进行练习提升时&#xff0c;经常会看到题目要求数据从大到小输出&#xff0c;从小到大输出&#xff0c;前一半从小到大输出&#xff0c;后一半从大到小输出等&#xff0c;那么这时候就需要用到排序算法&#xff0c;通过排序算法将数据按照一定的顺序进行排序。本文…

解决PyCharm 2023 Python Packages列表为空

原因是因为没有设置镜像源 展开 > 之后&#xff0c;这里 点击齿轮 添加一个阿里云的源 最后还需要点击刷新 可以选择下面的任意一个国内镜像源&#xff1a; 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirrors.aliyun.com/…

设计模式之-策略模式配合枚举

1、定义枚举接收不同的参数使用不同的handler, 2、定义个handerl接口&#xff0c;统一方法处理&#xff0c;每个handler实现该接口 public interface IMethodHandler<T, R> {/*** 处理统一入口** param req*/R process(T req); } java3、定义一个简单工厂统一处理 Comp…

送给正在入行的小白:最全最有用的网络安全学习路线已经安排上了,零基础入门到精通,收藏这一篇就够了

在这个圈子技术门类中&#xff0c;工作岗位主要有以下三个方向&#xff1a; 安全研发安全研究&#xff1a;二进制方向安全研究&#xff1a;网络渗透方向 下面逐一说明一下。 第一个方向&#xff1a;安全研发 你可以把网络安全理解成电商行业、教育行业等其他行业一样&#xf…

k8s 1.28.2 集群部署 harbor v2.11.1 接入 MinIO 对象存储

文章目录 [toc]提前准备什么是 HarborHarbor 架构描述Harbor 安装的先决条件硬件资源软件依赖端口依赖 Harbor 在 k8s 的高可用Harbor 部署Helm 编排YAML 编排创建 namespace导入镜像部署 Redis部署 PostgreSQL部署 Harbor core部署 Harbor trivy部署 Harbor jobservice部署 Ha…

RTSP流图片采样助手(yolov5)

在监控和视频分析领域&#xff0c;实时采样视频流中的图像数据是十分重要的。本文将介绍一个基于Python和Tkinter构建的RTSP流图片采样助手的设计与实现&#xff0c;旨在简化RTSP流的采样过程&#xff0c;并支持根据用户定义的特殊标签进行筛选。 项目概述 该项目的主要功能包…

Data+AI下的数据湖和湖仓一体发展史

DataAI下的数据湖和湖仓一体发展史 前言数据湖的“前世今生”AI时代的救星&#xff1a;湖仓一体湖仓一体实践演进未来趋势&#xff1a;智能化、实时化结语 前言 数据湖&#xff1f;湖仓一体&#xff1f;这是什么高科技新名词&#xff1f; 别急&#xff0c;我们慢慢聊。想象一…

ICT产业新征程:深度融合与高质量发展

在信息时代的浪潮中&#xff0c;每一场关于技术革新与产业融合的盛会都闪耀着智慧的光芒&#xff0c;引领着未来的方向。9月25日&#xff0c;北京国家会议中心内&#xff0c;一场聚焦全球信息通信业的顶级盛事——第32届“国际信息通信展”&#xff08;PT展&#xff09;隆重拉开…

Maven基于构建阶段分析多余的依赖

基于构建阶段 test compile 实现依赖分析 执行maven 命令: mvn dependency:analyze 关注:Maven-dependency-plugin 分析结果: [INFO] --- maven-dependency-plugin:2.10:analyze (default-cli) impl --- 配置依赖未使用的依赖项&#xff1a; [INFO] --- maven-dependency-…

Linux基础项目开发day2:量产工具——输入系统

文章目录 前言一、数据结构抽象1、数据本身2、设备本身3、input_manager.h 二、触摸屏编程1、touchscreen.c 三、触摸屏单元测试1、touchscreen.c2、上机测试 四、网络编程netiput.c 五、网络单元测试1、netiput.c2、client.c3、上机测试 六、输入系统的框架1、框架思路2、inpu…

数据库设计与开发—初识SQLite与DbGate

一、SQLite与DbGate简介 &#xff08;一&#xff09;SQLite[1][3] SQLite 是一个部署最广泛、用 C 语言编写的数据库引擎&#xff0c;属于嵌入式数据库&#xff0c;其作为库被软件开发人员嵌入到应用程序中。 SQLite 的设计允许在不安装数据库管理系统或不需要数据库管理员的情…

sublime配置(竞赛向)

我也想要有jiangly一样的sublime 先决条件 首先&#xff0c;到官网上下载最新的sublime4&#xff0c;然后在mingw官网上下载最新的mingw64 mingw64官网&#xff1a;左边菜单栏点击dowloads,然后选择MinGW-W64-builds(可能会有点慢)——然后有时候会变成选LLVM-minGW,接着选择…

linux c国际化

一种locale表示一种文化的各种数据的表示或显示方式&#xff0c;一种locale分成多个部分&#xff0c;不同的部分由category表示&#xff0c;每一种category下面定义了很多关键字keyword locale -a 查看所有支持的locale&#xff0c; locale 不带参 查看当前locale的各个categ…

大语言模型怎么写好提示词,看这篇就够了

对于任何输入&#xff0c;大语言模型都会给出相应的输出&#xff0c;这些输入都可以成为提示词&#xff0c;通常&#xff0c;提示词由指令和输入数据组成&#xff0c;指令是任务&#xff0c;输入数据是完成的要求&#xff0c;其中指令应该明确&#xff0c;用词不能模棱两可&…

centos7.9升级rockylinux8.8

前言 查看centos的版本 &#xff0c;我这台服务器是虚拟机,下面都是模拟实验 升级前一定要把服务器上配置文件&#xff0c;数据等进行备份 [rootlocalhost ~]#cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]#uname -a Linux jenkins_ser…

【C++进阶】AVL树的实现

1. AVL的概念 AVL树是最先发明的⾃平衡⼆叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性质的⼆叉搜索树&#xff1a;它的左右⼦树都是AV树&#xff0c;且左右⼦树的⾼度差的绝对值不超过1。AVL树是⼀颗⾼度平衡搜索⼆叉树&#xff0c;通过控制⾼度差去控制平衡…

SLM201A系列24V, 15mA - 60mA单通道线性恒流LED驱动芯片 灯带灯条解决方案

SLM201A系列型号&#xff1a; SLM201A15aa-7G SLM201A20aa-7G SLM201A25aa-7G SLM201A30aa-7G SLM201A35aa-7G SLM201A40aa-7G SLM201A45aa-7G SLM201A50aa-7G SLM201A55aa-7G SLM201A60aa-7G SLM201A 系列产品是用于产生单通道、高…