【网络入侵检测】基于源码分析Suricata的IP分片重组
【作者主页】只道当时是寻常
【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。
目录
目录
1.概要
2. 配置信息
2.1 名词介绍
2.2 defrag 配置
3. 代码实现
3.1 配置解析
3.1.1 defrag配置
3.1.2 主机系统策略
3.2 分片重组模块
3.2.1分片追踪器(DefragTracker )
3.2.2 获取分片追踪器(DefragGetTracker)
3.2.3 分片插入(DefragInsertFrag)
3.2.3.1 分片冲突策略
3.2.3.1.1 DEFRAG_POLICY_BSD
3.2.3.1.2 DEFRAG_POLICY_BSD_RIGHT
3.2.3.1.3 DEFRAG_POLICY_LINUX
3.2.3.1.4 DEFRAG_POLICY_WINDOWS
3.2.3.1.5 DEFRAG_POLICY_SOLARIS
3.2.3.2 获取主机系统策略
1.概要
👋 本文针对网络入侵检测中 Suricata 的 IP 分片重组模块展开源码分析。IP 分片重组是网络数据传输关键,对 NIDS 执行 DPI 至关重要。Suricata 作为开源高性能网络威胁检测引擎,通过分析其 IP 分片重组模块源码,解析该模块处理 IP 分片数据、监视重组数据包,并将重组数据传递给后续模块的过程,以确保检测准确完整。文中主要包含Suricata中分片配置、分片重组以及解决重组冲突信息。
2. 配置信息
2.1 名词介绍
IP 分片 | IP 分片是因不同网络链路 MTU 不同,当 IP 数据包大小超链路 MTU 时,将其拆成多个小数据包的机制。 |
IP 分片流 | 单个 IP 报文经分片处理后,由其形成的多个分片所构成的传输流,被称为 IP 分片流,其中各分片报文的 IP 包头 ID 标识保持一致。 |
分片重组引擎 | Suricata 中专门用于对 IP 分片报文实施内部重组的功能模块。 |
2.2 defrag 配置
在 Suricata 的配置文件中,defrag 关键字包含的配置信息用于配置分片重组引擎。其默认配置信息如下:
defrag:memcap: 32mb# memcap-policy: ignorehash-size: 65536trackers: 65535 # number of defragmented flows to followmax-frags: 65535 # number of fragments to keep (higher than trackers)prealloc: yestimeout: 60# Enable defrag per host settings
# host-config:
#
# - dmz:
# timeout: 30
# address: [192.168.1.0/24, 127.0.0.0/8, 1.1.1.0/24, 2.2.2.0/24, "1.1.1.1", "2.2.2.2", "::1"]
#
# - lan:
# timeout: 45
# address:
# - 192.168.0.0/24
# - 192.168.10.0/24
# - 172.16.14.0/24
-
memcap:设置分片重组引擎可申请的最大使用内存,这限制了碎片整理过程中内存的使用量。
-
memcap-policy:[drop-packet/pass-packet/reject/ignore(默认)],适用于IPS模式,例如在分片重组时空间申请失败等因素导致无法重组该分片时,对该分片采取的策略。
-
hash-size:设置哈希表中能存储的元素的上限。
-
trackers:设置预先申请的分片追踪器(DefragTracker )的数量,一般和 prealloc 配合使用,prealloc 为 yes,则申请执行数量的DefragTracker 存储在defragtracker_spare_q结构中,否则不申请。
-
max-frags:设置最大分片数量。
-
prealloc:见 "trackers" 字段解释。
-
timeout:设置分片重组超时时间,默认 60s。
-
host-config: 针对特定主机单独设置分片重组策略。
-
timeout:设置分片重组超时时间,默认 60s。
-
address:设置主机IP地址。
-
3. 代码实现
3.1 配置解析
3.1.1 defrag配置
DefragInit 函数是Suricata 解析配置文件中 Defrag 配置信息的入口函数,DefragPolicyLoadFromConfig 函数用于解析 defrag.host-config 相关的配置信息,DefragInitConfig 函数用于解析其它配置信息。
3.1.2 主机系统策略
在Suricata中 SCHInfoLoadFromConfig 函数主要用于加载配置文件中 host-os-policy 相关的配置信息。
host-os-policy 的配置格式如下所示,分号前面为操作系统类型,后面列表中包含主机的IP地址,不同的IP地址可使用逗号分割。Suricata依据用户配置的IP地址区分主机系统类型。
# Host specific policies for defragmentation and TCP stream
# reassembly. The host OS lookup is done using a radix tree, just
# like a routing table so the most specific entry matches.
host-os-policy:windows: [0.0.0.0/0]bsd: []bsd_right: []old_linux: []linux: [10.0.0.0/8, 192.168.1.100, "8762:2352:6241:7245:E000:0000:0000:0000"]old_solaris: []solaris: ["::1"]hpux10: []hpux11: []irix: []macos: []vista: []windows2k3: []
下面sc_hinfo_os_policy_map 结构用于将配置信息中主机类型转换成宏变量。
/** Enum map for the various OS flavours */
SCEnumCharMap sc_hinfo_os_policy_map[ ] = {{ "none", OS_POLICY_NONE },{ "bsd", OS_POLICY_BSD },{ "bsd-right", OS_POLICY_BSD_RIGHT },{ "old-linux", OS_POLICY_OLD_LINUX },{ "linux", OS_POLICY_LINUX },{ "old-solaris", OS_POLICY_OLD_SOLARIS },{ "solaris", OS_POLICY_SOLARIS },{ "hpux10", OS_POLICY_HPUX10 },{ "hpux11", OS_POLICY_HPUX11 },{ "irix", OS_POLICY_IRIX },{ "macos", OS_POLICY_MACOS },{ "windows", OS_POLICY_WINDOWS },{ "vista", OS_POLICY_VISTA },{ "windows2k3", OS_POLICY_WINDOWS2K3 },{ NULL, -1 },
};
3.2 分片重组模块
Defrag 函数作为分片重组引擎的入口函数,在网络数据包解码过程中发挥着关键作用。当解码进入网络层时,会根据数据包的 IP 版本调用 DecodeIPV4 或 DecodeIPV6 函数进行处理(有关具体的解码流程以及这两个函数的详细介绍,可查阅 【网络入侵检测】基于源码分析Suricata的解码模块)。在调用这两个解码函数期间,Defrag 函数可能会被触发。IPv4 报文触发的条件是:IP 包头中的偏移字段值大于零,或者更多分片标志位(MF)被设置为 1。只有满足这些条件,才会调用 Defrag 函数对分片数据包进行重组操作。IPv6不是本文重点,本文不再关注。
下面是 Suricata 源码中对于IPv4包头是否分片判断:
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,const uint8_t *pkt, uint16_t len)
{... .../* If a fragment, pass off for re-assembly. */if (unlikely(IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1)) {Packet *rp = Defrag(tv, dtv, p);if (rp != NULL) {PacketEnqueueNoLock(&tv->decode_pq, rp);}p->flags |= PKT_IS_FRAGMENT;return TM_ECODE_OK;}... ...
}
下面是分片重组模块四个主要函数:
-
Defrag:分片重组入口函数。
-
DefragGetTracker:获取分片追踪器(DefragTracker )。
-
DefragInsertFrag:执行分片重组操作。
-
DefragTrackerRelease:执行 DefragTracker 结构引用计数减一操作,并不是释放该对象。
下面是分片重组模块整体设计:
3.2.1分片追踪器(DefragTracker )
在 Suricata 中 DefragTracker 这个结构体尤为重要,该结构体用于跟踪和管理 IP 分片重组的过程。它的主要作用是记录与特定 IP 分片流相关的信息,以便在接收到所有分片后能够正确地重组原始数据包。下面是该结构体的结构:
/*** A defragmentation tracker. Used to track fragments that make up a* single packet.*/
typedef struct DefragTracker_ {SCMutex lock; /**< Mutex for locking list operations on* this tracker. */uint16_t vlan_id[VLAN_MAX_LAYERS]; /**< VLAN ID tracker applies to. */uint32_t id; /**< IP ID for this tracker. 32 bits for IPv6, 16* for IPv4. */uint8_t proto; /**< IP protocol for this tracker. */uint8_t policy; /**< Reassembly policy this tracker will use. */uint8_t af; /**< Address family for this tracker, AF_INET or* AF_INET6. */uint8_t seen_last; /**< Has this tracker seen the last fragment? */uint8_t remove; /**< remove */Address src_addr; /**< Source address for this tracker. */Address dst_addr; /**< Destination address for this tracker. */int datalink; /**< datalink for reassembled packet, set by first fragment */SCTime_t timeout; /**< When this tracker will timeout. */uint32_t host_timeout; /**< Host timeout, statically assigned from the yaml *//** use cnt, reference counter */SC_ATOMIC_DECLARE(unsigned int, use_cnt);struct IP_FRAGMENTS fragment_tree;/** hash pointers, protected by hash row mutex/spin */struct DefragTracker_ *hnext;struct DefragTracker_ *hprev;/** list pointers, protected by tracker-queue mutex/spin */struct DefragTracker_ *lnext;struct DefragTracker_ *lprev;
} DefragTracker;
下面我们挑选几个主要的变量进行解释:
-
vlan_id:记录 VLAN ID,用于标识分片所属的 VLAN 网络。
-
id:IP 分片的标识符(IP ID),用于区分不同的分片流。
-
proto: IP 协议类型(如 TCP、UDP 等),用于确定分片所属的协议。
-
policy:分片重组策略,不同的主机系统在遇到重组冲突时遵循的重组策略是不同的。
-
af:地址族,标识是 IPv4 (AF_INET) 还是 IPv6 (AF_INET6)。
-
seen_last:标记是否已经接收到最后一个分片。
-
remove:标记该跟踪器是否需要被移除。
-
src_addr:记录分片流的源地址。
-
dst_addr:记录分片流的目的地址。
-
datalink:数据链路层类型,由第一个分片设置。
-
timeout:超时时间,用于确定何时丢弃未完成的分片流。
-
fragment_tree: 用于存储分片的红黑树,按分片偏移量排序。
-
hnext 和 hprev: 哈希表指针,用于在哈希表中链接多个跟踪器。
-
lnext 和 lprev: 链表指针,用于在跟踪器队列中链接多个跟踪器。
👋 综上所述,我们能够明确,每个不同的 IP 分片流都与唯一的 DefragTracker 结构相对应。DefragTracker 结构借助红黑树,按照偏移顺序对当前 IP 分片流中的各个数据包进行存储。后续的分片存储、数据包重组等操作,均依赖这一结构体展开。
3.2.2 获取分片追踪器(DefragGetTracker)
在 Defrag 函数对分片包完成统计操作后,会调用 DefragGetTracker 函数,以查找当前分片报文是否存在对应的 DefragTracker 结构。若存在,则返回该 DefragTracker 结构;若不存在,则创建一个新的 DefragTracker 结构,用于存储该分片包所在分片流的相关信息。具体流程如下图所示:
3.2.3 分片插入(DefragInsertFrag)
调用 DefragGetTracker 后已经获取当前分片关联的 DefragTracker 对象,接着根据当前分片的偏移值,将分片插入到分片队列中。下面是分片插入操作流程图:
3.2.3.1 分片冲突策略
分片在重组的过程中可能出现新的分片与旧的分片出现冲突或者覆盖的现象,如下图所示(参考自TCP IP协议 卷2 第十章):
通过观察上图可以看到分片5与分片1和分片2发生重叠,分片7和分片3发生重叠,分片6与分片4发生重叠。其中分片1、2、3、4先到达目标主机,分片5、6、7后到达主机。
👋 为什么分片在传输过程中出现重叠现象?
在正常的网络通信中,IP分片的“Fragment Offset”字段应确保各分片数据在重组时无重叠。然而,攻击者可以故意设置多个分片的偏移量和长度,使它们在重组时发生重叠。
例如,攻击者可能发送两个分片:
分片A:偏移量为0,长度为100字节
分片B:偏移量为50,长度为100字节
在这种情况下,分片B的前50字节将覆盖分片A的后50字节,导致数据重叠。
👋 发生分片重叠时应该怎么处理?
不同操作系统和网络设备在处理重叠分片时的行为可能不同:
某些系统可能保留第一个到达的分片数据,忽略后续重叠部分。
另一些系统可能使用后到达的分片数据覆盖先前的内容。
还有的系统可能在检测到重叠时直接丢弃整个数据包。
Suricata 支持多种分片重组策略来适配多种不同的操作系统,而在配置文件中 host-os-policy 配置可指定目标主机系统类型。
3.2.3.1.1 DEFRAG_POLICY_BSD
该策略遵循左侧优先法,即优先保留左侧偏移较小的分片数据。如果新分片与旧分片完全重合的情况下,优先保留旧分片。如果新分片左侧偏移与旧分片左侧偏移相等的情况下,优先裁剪新分片数据。
该部分逻辑代码实现如下所示:
/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_BSD:if (frag_offset < prev->offset + prev->data_len) {if (prev->offset <= frag_offset) { /* We prefer the data from the previous* fragment, so trim off the data in the new* fragment that exists in the previous* fragment. */uint16_t prev_end = prev->offset + prev->data_len;if (prev_end > frag_end) { /* Just skip. *//* TODO: Set overlap flag. */goto done;}ltrim = prev_end - frag_offset;if ((next != NULL) && (frag_end > next->offset)) {next->ltrim = frag_end - next->offset;}goto insert;}/* If the end of this fragment overlaps the start* of the previous fragment, then trim up the* start of previous fragment so this fragment is* used.** See:* DefragBsdSubsequentOverlapsStartOfOriginal.*/if (frag_offset <= prev->offset && frag_end > prev->offset + prev->ltrim) {uint16_t prev_ltrim = frag_end - prev->offset;if (prev_ltrim > prev->ltrim) {prev->ltrim = prev_ltrim;}}if ((next != NULL) && (frag_end > next->offset)) {next->ltrim = frag_end - next->offset;}goto insert;}break;... ...
}
3.2.3.1.2 DEFRAG_POLICY_BSD_RIGHT
该策略遵循右侧覆盖策略,即右边的分片覆盖前面的分片数据。
3.2.3.1.3 DEFRAG_POLICY_LINUX
该策略遵循左侧优先法,即优先保留左侧偏移较小的分片数据。如果新分片与旧分片完全重合的情况下,优先保留新分片。如果新分片左侧偏移与旧分片左侧偏移相等的情况下,优先裁剪旧分片数据。
该部分逻辑代码实现如下所示:
/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_LINUX:/* Check if new fragment overlaps the end of previous* fragment, if it does, trim the new fragment.** Old: AAAAAAAA AAAAAAAA AAAAAAAA* New: BBBBBBBB BBBBBBBB BBBBBBBB* Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB*/if (prev->offset + prev->ltrim < frag_offset + ltrim &&prev->offset + prev->data_len > frag_offset + ltrim) {ltrim += prev->offset + prev->data_len - frag_offset;}/* Check if new fragment overlaps the beginning of* previous fragment, if it does, tim the previous* fragment.** Old: AAAAAAAA AAAAAAAA* New: BBBBBBBB BBBBBBBB BBBBBBBB* Res: BBBBBBBB BBBBBBBB BBBBBBBB*/if (frag_offset + ltrim < prev->offset + prev->ltrim &&frag_end > prev->offset + prev->ltrim) {prev->ltrim += frag_end - (prev->offset + prev->ltrim);goto insert;}/* If the new fragment completely overlaps the* previous fragment, mark the previous to be* skipped. Re-assembly would succeed without doing* this, but this will prevent the bytes from being* copied just to be overwritten. */if (frag_offset + ltrim <= prev->offset + prev->ltrim &&frag_end >= prev->offset + prev->data_len) {prev->skip = 1;goto insert;}break;... ...
}
3.2.3.1.4 DEFRAG_POLICY_WINDOWS
该策略遵循"先到先得"原则,即尽量保全先到来的数据包分片。除非新分片包含且不完全重合于旧分片的情况下,保留新分片。如果新分片左侧偏移与旧分片左侧偏移相等的情况下,优先裁剪新分片数据。
该部分逻辑代码实现如下所示:
/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_WINDOWS:/* If new fragment fits inside a previous fragment, drop it. */if (frag_offset + ltrim >= prev->offset + ltrim &&frag_end <= prev->offset + prev->data_len) {goto done;}/* If new fragment starts before and ends after* previous fragment, drop the previous fragment. */ if (frag_offset + ltrim < prev->offset + ltrim &&frag_end > prev->offset + prev->data_len) {prev->skip = 1;goto insert;}/* Check if new fragment overlaps the end of previous* fragment, if it does, trim the new fragment.** Old: AAAAAAAA AAAAAAAA AAAAAAAA* New: BBBBBBBB BBBBBBBB BBBBBBBB* Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB*/if (frag_offset + ltrim > prev->offset + prev->ltrim &&frag_offset + ltrim < prev->offset + prev->data_len) { ltrim += prev->offset + prev->data_len - frag_offset; goto insert;}/* If new fragment starts at same offset as an* existing fragment, but ends after it, trim the new* fragment. */if (frag_offset + ltrim == prev->offset + ltrim &&frag_end > prev->offset + prev->data_len) {ltrim += prev->offset + prev->data_len - frag_offset;goto insert;}break;... ...
}
3.2.3.1.5 DEFRAG_POLICY_SOLARIS
该策略遵循左侧优先法,即优先保留左侧偏移较小的分片数据。如果新分片与旧分片完全重合的情况下,优先保留旧分片。如果新分片左侧偏移与旧分片左侧偏移相等的情况下,优先裁剪新分片数据。
该部分逻辑代码实现如下所示:
/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_SOLARIS:if (frag_offset < prev->offset + prev->data_len) {if (frag_offset >= prev->offset) {ltrim = prev->offset + prev->data_len - frag_offset;}if ((frag_offset < prev->offset) &&(frag_end >= prev->offset + prev->data_len)) {prev->skip = 1;}goto insert;}break;... ...
}
3.2.3.2 获取主机系统策略
在Suricata的配置文件中通过host-os-policy关键字已经配置好主机系统策略,而在初始化DefragTracker对象时,即调用DefragTrackerInit函数时,会通过当前分片的IP地址,结合host-os-policy配置来选择重组策略。
调用逻辑如下所示:
在 DefragGetOsPolicy 函数中,Suricata会将不同的系统策略归为7类。注意,如果未配置,默认重组策略为DEFRAG_POLICY_BSD。
系统策略 | 分片重组策略 |
DEFRAG_POLICY_BSD | OS_POLICY_BSD |
OS_POLICY_HPUX10 | |
OS_POLICY_IRIX | |
DEFRAG_POLICY_BSD_RIGHT | OS_POLICY_BSD_RIGHT |
DEFRAG_POLICY_LINUX | OS_POLICY_OLD_LINUX |
OS_POLICY_LINUX | |
DEFRAG_POLICY_FIRST | OS_POLICY_OLD_SOLARIS |
OS_POLICY_HPUX11 | |
OS_POLICY_MACOS | |
OS_POLICY_FIRST | |
DEFRAG_POLICY_SOLARIS | OS_POLICY_SOLARIS |
DEFRAG_POLICY_WINDOWS | OS_POLICY_WINDOWS |
OS_POLICY_VISTA | |
OS_POLICY_WINDOWS2K3 | |
DEFRAG_POLICY_LAST | OS_POLICY_LAST |
分片重组策略结构如下所示:
/** Fragment reassembly policies. */
enum defrag_policies {DEFRAG_POLICY_FIRST = 1,DEFRAG_POLICY_LAST,DEFRAG_POLICY_BSD,DEFRAG_POLICY_BSD_RIGHT,DEFRAG_POLICY_LINUX,DEFRAG_POLICY_WINDOWS,DEFRAG_POLICY_SOLARIS,DEFRAG_POLICY_DEFAULT = DEFRAG_POLICY_BSD,
};
相关文章:
【网络入侵检测】基于源码分析Suricata的IP分片重组
【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 目录 目录 1.概要 2. 配置信息 2.1 名词介绍 2.2 defrag 配置 3. 代码实现 3.1 配置解析 3.1.1 defrag配置 3.1.2 主机系统策略 3.2 分片重组模块 3.2.1…...
“Cobalt Strike Aggressor脚本提权全解析:从监听器到SYSTEM/root的渗透实战指南“
目录 1. Aggressor脚本是什么?如何提权? 2. 这种脚本提权针对什么漏洞? 3. 如何发现可用于CS提权的漏洞? 4. Windows和Linux利用Aggressor脚本提权的全过程 Windows提权:CVE-2021-1732 (Win32k提权) Linux提权&a…...
为啥大模型一般将kv进行缓存,而q不需要
1. 自回归生成的特点 大模型(如 GPT 等)在推理时通常采用自回归生成的方式: 模型逐个生成 token,每次生成一个新 token 时,需要重新计算注意力。在生成第 t 个 token 时,模型需要基于前 t-1 个已生成的 t…...
一些模型测试中的BUG和可能解决方法
一些模型测试中的BUG和可能解决方法 模型一直重复反馈相同内容的问题查找思路 如下顺序也是排查优先级 检查提示词和上下文,保证提示词中没有类似的要求,然后再查看上下文是不是占满了token长度。检查一下选择的model是不是本身就有这样的问题尝试增加repeat_penalty(1.05、…...
智慧农业运维平台养殖—传感器管理监控设计—仙盟创梦IDE
智慧农业综合监测与智能执行系统简介 该系统围绕农业生产全流程,融合气象环境监测、农技指导精准推送及多维度智能控制,助力农业高效、科学发展。 气象环境与农技指导:于农业现场部署慧云智能物联网设备,实时监测空气温湿度、光照…...
linux中的日志分割
1.问题背景,nginx日志过大不好删除 [rootlocalhost cron.daily]# cd /lk/nginx/log/ [rootlocalhost log]# ll 总用量 2386188 -rw-r--r--. 1 root root 2078699697 5月 9 13:02 access.log -rw-r--r--. 1 root root 11138 5月 6 10:28 error.log [rootloc…...
零基础学Java——第十一章:实战项目 - 控制台应用开发
第十一章:实战项目 - 控制台应用开发 在前面的章节中,我们已经学习了Java的基础知识、面向对象编程、高级特性、文件IO、多线程、网络编程和数据库操作等内容。现在,是时候将这些知识应用到实际项目中了。本章我们将从最基础的控制台应用开始…...
从逻辑学视角理解统计学在数据挖掘中的作用
文章目录 一、引言:逻辑学与统计学的交汇1.1 问题的逻辑本质:为什么需要统计学解析数据1.2 数据挖掘中的三重逻辑关系:数据-模式-知识 二、统计学的逻辑基础2.1 归纳逻辑与统计推断2.2 假设检验的逻辑结构2.3 概率论:不确定性的逻…...
Cluster Interconnect in Oracle RAC
Cluster Interconnect in Oracle RAC (文档 ID 787420.1)编辑转到底部 In this Document Purpose Scope Details Physical Layout of the Private Interconnect Why Do We Need a Private Interconnect ? Interconnect Failure Interconnect High Availability Private Inte…...
OPENSSL-1.1.1的使用及注意事项
下载链接: OpenSSL1.1.1一个广泛使用的开源加密库资源-CSDN文库 OpenSSL 1.1.1 是一个广泛使用的开源加密库,以下是其使用方法及注意事项: 使用方法 安装: Linux系统: 从源码编译安装:访问 OpenSSL 官网…...
Element-UI字体图标不显示
原因 我在控制台查看请求后,发现elementUI的字体文件请求路径不对, 我的路径是/static/css/static/fonts/element-icons.535877f.woff, 正确的是/static/fonts/element-icons.535877f.woff 解决 build - utils function generateLoaders (loa…...
lambda 表达式
C 的 lambda 表达式 是一种轻量、内联的函数对象写法,广泛用于标准算法、自定义回调、事件响应等场景。它简洁且强大。以下将系统、详细地讲解 lambda 的语法、捕获规则、应用技巧和实际使用场景。 🧠 一、基本语法 [捕获列表](参数列表) -> 返回类型…...
vue3: pdf.js 2.16.105 using typescript
npm create vite vuepdfpreview //创建项目npm install vue-pdf-embed npm install vue3-pdfjs npm install pdfjs-dist2.16.105 <!--* |~~~~~~~|* | |* | |…...
自然语言处理-词性标注的基本概念
在自然语言处理过程中,进行词性标注是很有必要的一个步骤,词性揭示了一个词的类别,识别每个词的词性可以分析句子的语法和结构,从而为后续的命名实体识别、句法分析、情感分析、信息抽取以及机器翻译等文本分析任务提供必要且有用…...
电机密集型工厂环境下的无线通信技术选型与优化策略
点击下面图片带您领略全新的嵌入式学习路线 🔥爆款热榜 88万阅读 1.6万收藏 在电机、变频器、电焊机等强电磁干扰源遍布的工业环境中,无线通信系统的可靠性面临严峻挑战。本文从抗干扰能力、传输稳定性、实时性需求三大核心维度出发,结合工…...
【软件安装那些事 2 】Multisim 14.3 安装教程(中文版)步骤完整不跳步 { 附百度网盘中软件提取下载链接,永久有效 }
百度网盘分享的文件:Multisim 14.3 安装包 中文 (永久有效) 链接: https://pan.baidu.com/s/1XE4X9_M496lyHCN3DGrOzw?pwd4yku 提取码: 4yku 1、解压完成后,打开【Setup】文件夹 2、右击【Install】,选择…...
NextDenovo2.5.2安装与使用-生信工具53
01 NextDenovo 简介 适用于三代数据基因组组装! NextDenovo 是一个基于字符串图(String Graph)的长读段(如 PacBio CLR, ONT)从头组装工具。它采用类似于 Canu 的“先纠错后组装”(correct-th…...
结构性变革与新兴机遇
近年来,全球就业市场正经历深刻的结构性变革。受技术进步、产业升级、人口结构变化及全球经济格局调整的影响,传统就业模式被重塑,新的职业机会不断涌现。本文将分析当前就业市场的主要趋势,并探讨其对劳动者、企业和政策制定者的…...
第20篇:Linux设备驱动程序入门<七>
Q:如何编写定时器中断驱动内核模块? A:使用在FPGA中实现的间隔定时器FPGA Timer0,寄存器接口基地址为0x00002000,时钟频率100MHz,中断ID为72。调用这个定时器需要向Counter start value寄存器写入适当的值…...
基于Transformer与SHAP可解释性分析的神经网络回归预测模型【MATLAB】
基于Transformer与SHAP可解释性分析的神经网络回归预测模型【MATLAB】 在当今的数据科学与人工智能领域,构建一个高精度的预测模型固然重要,但越来越多的应用场景开始关注模型的可解释性。尤其在金融、医疗、工业控制等对决策透明度要求较高的领域&…...
基于Java和GeoTools的根据矢量BBOx自动生成格网文件实践
目录 前言 一、基础数据介绍及生成方法简介 1、矢量数据处理 2、格网生成算法 二、代码实现 1、根据Shp计算Bounds 2、生成经纬网要素集合 3、写入 Shapefile 三、结果输出与验证 1、格网文件输出格式 2、GIS工具验证 四、总结 前言 在当今数字化与信息化高速发展的…...
[docker基础二]NameSpace隔离实战
目录 一 实战目的 二 基础知识 1)dd 命令详解 2)mkfs命令详解 3)df命令详解 4)mount 命令详解 5)unshare命令详解 三 实战操作一(PID隔离) 四 实战操作二(MOunt隔离) 1)创建 Mount 隔离进程 2)在新进程里边,创建空白文件&#…...
PIC18F45K80 ECAN模块使用
PIC18F45K80的CAN使用过程遇到一些问题,记录一下,主要是代码的理解。 在MPLAB X中配置工程: 1,在MCC中添加ECAN外设 2,CAN通讯有波特率的概念,整一个CAN网络需要运行在同一个速率。这里我们把他配置到12…...
RuntimeError: expected scalar type ComplexDouble but found Float
要解决 RuntimeError: expected scalar type ComplexDouble but found Float 错误,请按照以下步骤操作: 步骤 1:定位错误发生的位置 查看完整的错误堆栈跟踪,确定具体是哪一行代码引发了错误。例如:RuntimeError: exp…...
基于DeepSeek的韦恩图绘制:方法、优化与应用
一、研究背景与冲突 在生物信息学、医学研究、数据科学等众多领域,清晰展示数据集之间的交集关系至关重要。韦恩图(Venn diagram)作为一种有效的可视化工具,能以直观的图形呈现多个数据集之间的重叠情况,帮助研究者快…...
自动驾驶的“眼睛”:用Python构建智能障碍物检测系统
自动驾驶的“眼睛”:用Python构建智能障碍物检测系统 在自动驾驶技术日益成熟的今天,障碍物检测系统成了汽车智能化不可或缺的部分。无论是高速公路上的突发状况,还是城市街道中的行人与车辆,准确识别障碍物并及时反应,是保证行车安全的关键。 那么,我们如何用Python构…...
基于HTML+JavaScript+CSS实现教学网站
摘要 21世纪是信息化的时代,信息化物品不断地涌入我们的生活。同时,教育行业也产生了重大变革。传统的身心教授的模式,正在被替代。互联网模式的教育开辟了一片新的热土。 这算是对教育行业的一次重大挑战。截至目前,众多教育行…...
【Pandas】pandas DataFrame all
Pandas2.2 DataFrame Computations descriptive stats 方法描述DataFrame.abs()用于返回 DataFrame 中每个元素的绝对值DataFrame.all([axis, bool_only, skipna])用于判断 DataFrame 中是否所有元素在指定轴上都为 True pandas.DataFrame.all() pandas.DataFrame.all() 方…...
何时需要import css文件?怎么知道需要导入哪些css文件?为什么webpack不提示CSS导入?(导入css导入规则、css导入规范)
文章目录 何时需要import css文件?**1. 使用模块化工具(如 Webpack、Vite、Rollup 等)****适用场景:****示例:****优点:** **2. 动态加载 CSS(按需加载)****适用场景:***…...
智汇云舟亮相第二十七届北京科博会
5月8日,备受瞩目的第二十七届中国北京国际科技产业博览会(以下简称:北京科博会)在国家会议中心盛大开幕。作为我国科技领域的重要盛会,北京科博会汇聚了众多前沿科技成果与创新力量,为全球科技产业交流搭建…...
ThreadLocal
9.1.1 面试题 ThreadLocal中ThreadLocalMap的数据结构和关系ThreadLocal的key是弱引用,这是为什么?ThreadLocal内存泄漏问题你知道吗?ThreadLocal中最后为什么要加remove方法?...
【高并发内存池】从零到一的项目之centralcache整体结构设计及核心实现
个人主页 : zxctscl 专栏 【C】、 【C语言】、 【Linux】、 【数据结构】、 【算法】 如有转载请先通知 文章目录 前言1. central cache整体结构2. central cache基础结构2.1 span类设计2.2 SpanList带头双向循环链表设计2.3 central cache类设计 3. central cache核…...
(pnpm)引入 其他依赖失败,例如‘@element-plus/icons-vue‘失败
当我们在开发项目的时候,利用了 pnpm 来进行管理,可能有些依赖就无法引入,这是因为 pnpm 和 npm 管理包的方式不一样, 举个例子,假如我们现在需要安装一个 A 包,A 包依赖 B 包, 此时我们通过 …...
面试题:请解释Java中的线程池(ThreadPoolExecutor)的工作原理,并说明如何自定义线程池
线程池(ThreadPoolExecutor)的工作原理 线程池是一种用于管理和复用线程的机制,它可以减少线程创建和销毁的开销,提高程序的执行效率。ThreadPoolExecutor是Java中实现线程池的一个类,它位于java.util.concurrent 包中…...
Windows Server 2025开启GPU分区(GPU-P)部署DoraCloud云桌面
本文描述在ShareStation工作站虚拟化方案的部署过程。 将服务器上部署 Windows Server、DoraCloud,并创建带有vGPU的虚拟桌面。 GPU分区技术介绍 GPU-P(GPU Partitioning) 是微软在 Windows 虚拟化平台(如 Hyper-V)中…...
WEB前端表单及表格标签综合案例
表单标签综合案例: 源代码: <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>…...
HTML应用指南:利用POST请求获取全国德邦快递服务网点位置信息
德邦快递作为中国领先的综合性物流服务提供商,自1996年成立以来,始终致力于为客户提供高效、安全的大件快递及其他物流解决方案。德邦快递凭借其强大的直营模式、“最后一公里”的优质服务以及对科技的持续投入,在竞争激烈的物流市场中占据了重要位置。特别是在大件快递领域…...
【Linux网络】应用层自定义协议与序列化
应用层自定义协议与序列化 应用层 我们程序员写的一个个解决我们实际问题,满足我们日常需求的网络程序,都是在应用层. 协议是一种"约定".Socket的接口,在读写数据时,都是按"字符串"的方式来发送接收的.如果我们要传输一些"结构化的数据"怎么办…...
Excel提取单元格特定符号左右两边内容
公式: RIGHT(字符串, 字符个数) :从字符串右边开始,提取指定字数内容 公式应用: RIGHT(A1, LEN(A1) - SEARCH(“-”, A1))—提取单元格A1中符号“-”右边的字符串 LEN(A1) - SEARCH(“-”, A1) 即是返回符号“-”右边的字符串长…...
集群/微服务/分布式
目录 介绍 集群 微服务 优点 缺点 如何管理和监控微服务架构中的多个微服务? 服务治理 配置管理 监控与告警 容器化与编排 安全管理 分布式 三者关系 分布式和集群的区别是什么? 概念 工作方式 节点角色 应用场景 故障处理 微服务 微…...
安装docker
安装docker 一、关闭防火墙和SELinux 1.1systemctl stop firewalld 1.2setenfoce 0 二、配置内核转发以及网桥过滤 2.1vi /etc/sysctl.d/k8s.conf 2.2sysctl -p /etc/sysctl.d/k8s.conf :让文件生效 2.3modprobe br_netfilter:加载模块 若未生效成功…...
热力图是什么?三分钟学会热力图数据分析怎么做!
目录 一、热力图是什么? (一)基本概念 (二)常见类型 (三)优点 二、热力图分析工具 (一)FineBI (二)Tableau (三)P…...
Spring、SpringMVC、SpringBoot、SpringCloud 联系与区别
Spring、SpringMVC、SpringBoot、SpringCloud 联系与区别 一、引言 在 Java 企业级开发中,Spring 家族框架是绕不开的核心技术栈。从基础架构到 Web 开发,再到微服务架构,Spring 系列框架通过层层抽象,逐步简化开发复杂度。本文…...
操作系统导论——第26章 并发:介绍
本章介绍为单个运行进程提供的新抽象:线程(thread)。经典观点是一个程序只有一个执行点(一个程序计数器,用来存放要执行的指令),但多线程(multi-threaded)程序会有多个执…...
如何使用测试软件 Jmeter
第一步,点击 编辑 添加线程组 第二步,右键单击线程组,添加取样器 HTTP 请求 第三步,设置请求路径 第四步,添加 查看结果树 用于查看请求响应 最后点击绿色小三角启动即可...
HarmonyOS NEXT 免费无广告看电影app:从想法到实现的经验总结
学习一项新技能,最好也是最快的方法就是动手实战。学习鸿蒙也一样,给自己定一个小目标,直接找项目练,这样进步是最快的。最近,我在网上看到360周董的一句话:“想干什么就去干,干得烂总比不干强!…...
《算法导论(第4版)》阅读笔记:p14-p16
《算法导论(第4版)》学习第 9 天,p14-p16 总结,总计 3 页。 一、技术总结 无。 二、英语总结(生词:2) 1. in light of (1)释义 idiom. in light of 是美式用法,英式用法是 in the light of。take sth into consideration(鉴…...
kuka, fanuc, abb机器人和移动相机的标定
基础知识 : 一, 9点标定之固定相机标定: 图1: 固定位置相机拍照 因为相机和机器人的基坐标系是固定的, 所以在海康威视相机的9点标定功能栏中, 填上海康使用“圆查找”捕捉到的坐标值, 再将机器人显示的工具坐标系在基坐标系的实时位置pos_act值填入物理坐标X, Y中即可 图2:…...
【MyBatis-6】MyBatis动态SQL:灵活构建高效数据库查询的艺术
在现代企业级应用开发中,与数据库的交互是不可或缺的核心部分。MyBatis作为一款优秀的持久层框架,因其简洁、灵活和高效而广受开发者喜爱。其中,动态SQL功能更是MyBatis的一大亮点,它允许开发者根据不同条件灵活构建SQL语句&#…...
从零开始理解FlashAttention:算法细节图解
🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创…...