尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
libnids源码深度解读:TCP重组与IP分片注释实战
简介这份资源是 libnids 1.20 源码的深度解读版本作者在原始代码基础上补充了大量中文注释面向网络安全方向的学习者、入侵检测系统开发者以及希望理解 TCP/IP 协议栈实现细节的工程师。libnids 作为经典的开源 NIDS 库核心价值在于数据包捕获、协议解析、TCP 流重组与事件回调机制而注释版源码恰好降低了阅读门槛帮助读者快速定位 IP 头部解析、tcp_stream 结构体管理、add_seq/find_seq 序列号处理以及 tcp_reassemble 重组逻辑等关键实现。资源包共 65 个文件以 15 个 c 源文件和 7 个 h 头文件为主体辅以工程配置、文档与测试样例整体约 245KB结构紧凑。目前已有 466 人学习下载适合结合 libpcap 抓包实践深入掌握网络流量分析与自定义检测规则的开发思路。1. libnids 源码解读加了大量的注释从抓包到重组一个被低估的中间层很多人第一次接触网络流量分析都是从 libpcap 的pcap_loop回调里直接解析以太网帧开始的。写不了几百行就会发现一个绕不过去的问题TCP 流是分段的一个完整的 HTTP 请求可能散落在七八个包里顺序、重传、乱序、分片全得自己处理。libnids 就是在这个位置上存在的——它架在 libpcap 之上帮你把散落的 TCP 段拼成一条完整的字节流再通过回调交给你。标题里说的“源码解读加了大量的注释”本质上是在做一件很有价值的事把 libnids 这个中间层从黑匣子变成可读、可改、可调试的代码。它适合两类人一类是做 IDS、流量审计、协议还原的工程师需要理解重组逻辑才能定位丢包和误判另一类是想自己写一个轻量级 TCP 重组模块的人libnids 的源码结构清晰、依赖少是很好的参考底本。这篇文章不逐行念代码而是按“它怎么工作、关键结构体怎么用、注释该加在哪、坑在哪”的顺序把这份带注释的源码解读讲透。2. libnids 的三层结构抓包、重组、应用回调是怎么串起来的libnids 的代码量不大核心文件通常集中在nids.c、tcp.c、ip_fragment.c、session.c这几个里。理解它的第一步不是看某个函数而是先看清它的三层分工。这三层如果混在一起读注释加得再多也会乱。2.1 从 pcap 回调到 nids 入口数据是怎么进来的libnids 对外暴露的启动接口一般是nids_init()加nids_run()或者用nids_pcap_handler挂到自己的 pcap 循环里。数据进入 libnids 的第一站是链路层解析它需要知道链路类型是 Ethernet、PPP 还是 RAW IP这个由nids_init里的nids_datalink或自动探测决定。/* nids.c 中链路层分发的大致逻辑注释版 */ int nids_pcap_handler(u_char *par, struct pcap_pkthdr *h, u_char *data) { struct nids_chksum_ctl *ctlp; /* 先做校验和开关控制libnids 允许按需关闭校验和计算以提速 */ if (nids_chksum_ctl) { /* 这里遍历控制链表决定当前包是否跳过校验和 */ } /* 根据链路类型偏移到 IP 头Ethernet 是 14 字节PPP 不同 */ switch (nids_datalink) { case NIDS_DATALINK_ETHERNET: data 14; break; case NIDS_DATALINK_RAW: break; /* 其他链路类型省略 */ } /* 进入 IP 层处理分片重组就在这里发生 */ return nids_ip_process(h, data); }这段注释要说明的关键点是链路层偏移量不是固定的nids_datalink决定了从哪个字节开始是 IP 头。很多人自己改 libnids 支持新链路类型时翻车就是因为只改了偏移量没同步改nids_init里的探测逻辑。参数上h是 pcap 包头data是原始帧nids_chksum_ctl是一个全局链表用来控制哪些包跳过校验和在高流量场景下关掉校验和能省不少 CPU但会牺牲正确性。2.2 IP 分片重组ip_fragment.c里的哈希表和超时链表IP 分片重组是 libnids 里第一个容易读晕的地方。它的核心是一个哈希表加一个双向链表哈希表按源 IP、目的 IP、协议、IP ID索引分片队列链表按时间排序用于超时清理。/* ip_fragment.c 中分片队列结构的关键字段注释版 */ struct ip_frag { struct ip_frag *next; /* 超时链表的下一个 */ struct ip_frag *prev; /* 超时链表的上一个 */ struct ipfrag *fragments; /* 已到达的分片链表按偏移排序 */ unsigned int af; /* 地址族IPv4 或 IPv6 */ unsigned int offset; /* 当前已覆盖的字节范围用于判断是否收齐 */ struct timeval timeout; /* 该队列的过期时间 */ /* 源/目的地址、IP ID、协议等作为哈希 key 的字段 */ };注释要落在两个地方一是offset的更新时机每收到一个分片要把它的偏移和长度合并进offset只有offset覆盖了完整数据报长度才算收齐二是timeout的刷新libnids 默认分片超时是 30 秒左右这个值在nids_params里可以调。常见坑是分片乱序到达时fragments链表要按偏移插入排序如果只做头插重组出来的数据顺序就是错的。参数上哈希表大小和超时时间是两个最常调的旋钮高并发场景下哈希表太小会导致链表过长查找变慢。2.3 TCP 重组与状态机tcp.c里最值得加注释的部分TCP 重组是 libnids 的核心价值所在。它维护一个 TCP 连接表每个连接有struct tcp_stream里面保存了双向的序列号状态、半连接队列、以及一个用于重组的缓冲区。/* tcp.c 中 TCP 流结构的关键字段注释版 */ struct tcp_stream { struct tcp_stream *next; /* 连接哈希表的下一个 */ struct tuple4 addr; /* 四元组源IP、源端口、目的IP、目的端口 */ struct half_stream client; /* 客户端方向的状态和缓冲区 */ struct half_stream server; /* 服务端方向的状态和缓冲区 */ int nids_state; /* 连接状态NIDS_JUST_EST / NIDS_DATA / NIDS_CLOSE 等 */ /* 时间戳、超时、重传计数等 */ }; struct half_stream { char *data; /* 重组缓冲区存放已按序到达的数据 */ int count; /* 当前缓冲区中有效字节数 */ int offset; /* 已交付给应用层的字节数 */ unsigned int seq; /* 下一个期望的序列号 */ /* 窗口、重传、乱序队列等 */ };这里注释的重点是seq和offset的区别seq是 TCP 层面的下一个期望序列号offset是已经通过回调交给应用层的字节位置。两者不同步是正常的因为数据可能先缓存在data里等应用层回调消费后才推进offset。另一个重点是nids_state的流转NIDS_JUST_EST表示连接刚建立NIDS_DATA表示有数据可读NIDS_CLOSE表示连接关闭。应用层回调就是根据这个状态决定做什么。参数上half_stream的缓冲区大小和乱序队列长度会影响内存占用和重组能力默认值在nids_params里高流量下需要根据实际情况调。3. 把注释加在刀刃上源码解读的四个关键切入点给 libnids 源码加注释不是每行都写“这是赋值”。真正有价值的注释集中在四个地方状态流转、边界条件、内存生命周期、以及和协议规范的对应关系。这一章按这四个切入点展开每个都给出可操作的注释方法和代码示例。3.1 状态流转注释把nids_state的每个分支写清楚libnids 的应用层回调里最常见的写法是switch (nids_state)。如果不把每个状态的含义和触发条件注释清楚读代码的人根本不知道NIDS_DATA和NIDS_CLOSE之间还有没有中间态。/* 应用层回调中状态处理的注释模板 */ void nids_callback(struct tcp_stream *ts, void **param) { switch (ts-nids_state) { case NIDS_JUST_EST: /* 连接刚建立此时还没有数据。 * 可以在这里决定是否要监控这条连接 * 如果返回 0libnids 会继续跟踪 * 如果调用 nids_discard则丢弃后续数据。 */ ts-client.collect 1; /* 开启客户端数据收集 */ ts-server.collect 1; /* 开启服务端数据收集 */ break; case NIDS_DATA: /* 有新的按序数据到达数据在 ts-client.data 或 ts-server.data 中 * 有效长度是 ts-client.count - ts-client.offset。 * 注意这里的数据可能只是部分不要假设一次回调就是完整消息。 */ if (ts-client.count ts-client.offset) { /* 处理客户端数据 */ } break; case NIDS_CLOSE: /* 连接正常关闭或者超时被清理。 * 此时缓冲区里可能还有未消费的数据需要做收尾处理。 */ break; case NIDS_RESET: /* 连接被 RST 重置通常意味着异常断开。 */ break; case NIDS_TIMEOUT: /* 连接超时libnids 主动清理。 */ break; } }这段注释的价值在于它把每个状态的“什么时候来”和“来了该干什么”写在一起。特别是NIDS_DATA里要强调“一次回调不等于一条完整消息”这是新手最容易踩的坑——他们往往在第一次NIDS_DATA里就假设拿到了完整请求结果遇到大请求就解析失败。参数上collect字段控制是否收集数据如果只关心连接元信息不关心内容可以不开省内存。3.2 边界条件注释序列号回绕和缓冲区满的处理TCP 序列号是 32 位无符号数回绕是必须处理的边界。libnids 内部用seq比较时有一套自己的逻辑如果不注释清楚读代码的人会以为直接比大小就行。/* tcp.c 中序列号比较的注释示例 */ /* 判断序列号 a 是否在 b 之前考虑回绕。 * 不能直接用 a b因为 32 位序列号会从 0xFFFFFFFF 回绕到 0。 * libnids 的做法是看差值如果 (int)(a - b) 0则认为 a 在 b 之前。 * 这个技巧依赖有符号整数溢出行为在大多数平台成立。 */ #define SEQ_LT(a, b) ((int)((a) - (b)) 0) #define SEQ_LEQ(a, b) ((int)((a) - (b)) 0)另一个边界是缓冲区满。half_stream的data缓冲区不是无限增长的当应用层回调消费太慢缓冲区会满此时 libnids 的行为需要注释清楚是丢弃新数据还是覆盖旧数据常见做法是丢弃新数据并记录丢包计数。参数上缓冲区大小在nids_params里默认值适合一般流量但如果你的应用层处理慢要么调大缓冲区要么在回调里尽快消费。3.3 内存生命周期注释谁分配、谁释放、什么时候释放libnids 里涉及动态内存的地方主要是分片队列、TCP 流结构、以及重组缓冲区。注释要明确每个指针的归属。/* session.c 中连接清理的注释示例 */ void nids_free_tcp_stream(struct tcp_stream *ts) { /* 释放半连接缓冲区client.data 和 server.data 由 libnids 分配 * 应用层不要自己 free也不要在回调外持有这些指针。 */ if (ts-client.data) { free(ts-client.data); ts-client.data NULL; } if (ts-server.data) { free(ts-server.data); ts-server.data NULL; } /* 从哈希表和超时链表中摘除然后释放 ts 本身 */ /* ... */ free(ts); }注释的关键是告诉读者client.data和server.data的生命周期由 libnids 管理应用层只能在回调期间使用回调返回后指针可能失效。这是血泪经验——很多人把data指针存到自己的结构里等回调返回后再用结果读到已释放内存程序随机崩溃。参数上没有可调的但理解这一点能避免大量调试时间。3.4 协议对应注释把代码和 RFC 条款挂上钩libnids 的 TCP 状态机实现和 RFC 793 的对应关系是注释里最能提升可读性的部分。比如三次握手的状态流转、TIME_WAIT 的处理、以及窗口更新。/* tcp.c 中握手处理的注释示例 */ /* 对应 RFC 793 的 3.4 节连接建立。 * 收到 SYN 时创建 tcp_stream状态置为 NIDS_JUST_EST * 收到 SYNACK 时更新序列号 * 收到 ACK 时确认连接建立后续数据进入 NIDS_DATA 状态。 * 注意libnids 不完整实现所有 TCP 状态它只关心重组所需的最小状态集。 */这种注释的价值在于当代码行为和预期不符时可以快速定位是 libnids 的实现简化还是自己的理解有误。比如 libnids 对 TIME_WAIT 的处理就比较简化不会等完整的 2MSL而是用超时机制清理。参数上超时时间在nids_params里默认值偏短长连接场景下可能需要调大。4. 编译、调试与验证让带注释的源码真正跑起来读完源码、加完注释下一步是让它跑起来并验证行为。这一章给出从编译到验证的完整路径包括编译选项、调试手段、以及怎么确认重组逻辑正确。4.1 编译 libnids 的最小命令与依赖libnids 依赖 libpcap 和 libnet部分功能需要。在常见 Linux 发行版上先装开发包再编译。# 安装依赖以 Debian/Ubuntu 系为例 sudo apt-get install libpcap-dev libnet1-dev # 进入源码目录生成配置脚本并编译 ./configure --prefix/usr/local make sudo make install # 如果只想编译静态库用于调试 make clean ./configure --enable-static --disable-shared make CFLAGS-g -O0参数说明--enable-static生成静态库方便用 gdb 单步调试CFLAGS-g -O0关闭优化并保留调试符号这样在 gdb 里能看到变量值否则优化后的代码会跳来跳去。注意libnids 的configure脚本会探测 libpcap 和 libnet如果 libnet 没装部分功能会被禁用但核心 TCP 重组不受影响。4.2 用 gdb 断在关键函数上验证重组逻辑编译出带调试符号的版本后可以用 gdb 断在tcp.c的关键函数上观察tcp_stream的状态变化。# 启动 gdb加载你的测试程序 gdb ./your_test_program # 断在 TCP 数据处理的入口 (gdb) break nids_tcp_process (gdb) run -i eth0 # 命中后打印当前流的状态 (gdb) print *ts (gdb) print ts-client.seq (gdb) print ts-client.count (gdb) print ts-client.offset逻辑说明nids_tcp_process是 TCP 层处理的主入口断在这里能看到每个包进来时流的状态。重点观察seq是否按预期推进count和offset的差值是否等于待消费数据量。如果发现seq跳变可能是重传或乱序需要检查fragments或乱序队列的处理。参数上gdb 的print可以配合set print pretty on让结构体输出更易读。4.3 用构造流量验证从 pcap 文件回放最可控的验证方式是用 pcap 文件回放而不是抓实时流量。可以先用 tcpdump 抓一段包含完整 TCP 会话的流量然后用 libnids 处理这个文件。# 抓一段包含 HTTP 请求的流量 sudo tcpdump -i eth0 -w test.pcap tcp port 80 -c 100 # 用 libnids 处理这个文件假设你的测试程序支持 -r 参数 ./your_test_program -r test.pcap逻辑说明回放的好处是流量固定每次运行结果一致方便对比注释前后的行为差异。如果你的测试程序不支持-r可以改nids_init里的 pcap 打开方式把pcap_open_live换成pcap_open_offline。参数上-c 100限制抓包数量避免文件过大过滤表达式tcp port 80只抓 HTTP减少干扰。4.4 验证重组正确性的三个检查点跑起来之后怎么确认重组是对的三个检查点第一对比 libnids 重组出的数据和 tcpdump 里看到的原始负载是否一致第二检查NIDS_CLOSE时count和offset是否相等如果不等说明有数据没被消费第三用nids_params里的统计字段看丢包和超时计数。/* 在回调里打印统计信息验证重组完整性 */ case NIDS_CLOSE: printf(client: count%d offset%d\n, ts-client.count, ts-client.offset); printf(server: count%d offset%d\n, ts-server.count, ts-server.offset); /* 如果 count ! offset说明有数据未被应用层消费 */ break;参数说明count是缓冲区里累计的有效字节offset是已交付的字节。正常情况下连接关闭时两者应该相等。如果count offset要么是应用层回调没及时消费要么是缓冲区满了丢弃了数据。这个检查点能快速定位重组逻辑或应用层处理的问题。5. 避坑与排查libnids 源码解读中最容易翻车的五个地方这一章集中写踩坑记录每条按“现象 → 原因 → 解决”展开。这些坑在源码解读和实际使用中都会遇到提前知道能省很多时间。5.1 现象重组出的数据缺一段但抓包看包是全的原因最常见的是 IP 分片重组时offset更新逻辑有误或者分片超时太短后面的分片到达时前面的已经被清理。另一个可能是 TCP 乱序队列溢出乱序包被丢弃。解决先确认是不是分片问题用tcpdump -vv看是否有分片标志。如果是分片检查ip_fragment.c里offset的合并逻辑确保每个分片的偏移和长度都正确累加。如果是乱序调大nids_params里的乱序队列长度或者在回调里尽快消费数据减少缓冲区压力。5.2 现象程序运行一段时间后内存持续增长原因TCP 流结构没有正确释放。libnids 依赖超时机制清理连接如果超时时间设得太长或者应用层没有正确处理NIDS_CLOSE连接会一直留在哈希表里。解决检查nids_params里的超时设置默认值通常够用但长连接场景下要确认连接确实会关闭。另外在NIDS_CLOSE回调里不要持有tcp_stream指针回调返回后 libnids 会释放它。如果自己分配了内存挂在param上要在关闭时释放。5.3 现象gdb 调试时变量值显示为 optimized out原因编译时开了优化变量被寄存器分配或消除。这是调试带注释源码时最常见的问题。解决重新编译时加-O0 -g并确保configure没有覆盖 CFLAGS。如果用的是 Makefile直接改CFLAGS变量。注意libnids 的configure脚本可能会追加自己的优化选项检查生成的 Makefile 确认最终编译参数。5.4 现象回调里读到的数据顺序和预期不一致原因TCP 重组是按序列号排序的但如果应用层在NIDS_DATA里直接拼接数据而回调可能被多次触发拼接顺序取决于回调触发顺序。libnids 保证按序交付但一次回调的数据量不固定。解决不要在回调里假设一次拿到完整消息。正确做法是维护自己的缓冲区把每次NIDS_DATA的数据追加进去然后按协议格式判断消息是否完整。参数上ts-client.count - ts-client.offset是本次可读的字节数读完后要更新offset或调用nids_discard告诉 libnids 已消费。5.5 现象高流量下丢包严重重组不完整原因libnids 是单线程处理高流量下 pcap 缓冲区溢出或者 libnids 内部处理不过来。另外校验和计算也会消耗 CPU。解决先调大 pcap 缓冲区在nids_init之前用pcap_set_buffer_size设置。然后考虑关闭校验和计算通过nids_chksum_ctl控制。如果还是不够需要做多线程或分流处理但 libnids 本身不是线程安全的多线程需要自己加锁或每个线程独立实例。参数上nids_params里的pcap_timeout和缓冲区大小是两个关键旋钮。6. 进阶把注释变成可复用的调试能力带注释的源码解读最终价值不是注释本身而是通过注释建立起来的调试能力。这一章给两个进阶方向一是用注释里的检查点做自动化验证二是基于 libnids 的重组逻辑写自己的轻量级重组模块。先看自动化验证。在注释里标记的关键状态和边界条件可以转成断言或日志检查点。比如在NIDS_CLOSE时检查count offset如果不相等就打印警告。这个检查可以做成宏在调试版本里开启发布版本里关闭。/* 调试宏在关键状态检查不变量 */ #ifdef NIDS_DEBUG #define NIDS_CHECK(cond, msg) \ do { if (!(cond)) fprintf(stderr, [NIDS_CHECK] %s:%d %s\n, __FILE__, __LINE__, msg); } while (0) #else #define NIDS_CHECK(cond, msg) do {} while (0) #endif /* 在 NIDS_CLOSE 里使用 */ case NIDS_CLOSE: NIDS_CHECK(ts-client.count ts-client.offset, client data not fully consumed); NIDS_CHECK(ts-server.count ts-server.offset, server data not fully consumed); break;这个宏的好处是把注释里的“应该怎样”变成运行时的“实际怎样”一旦不满足就报警。参数上NIDS_DEBUG在编译时定义调试版本加-DNIDS_DEBUG发布版本不加零开销。再看自己写重组模块。libnids 的重组逻辑可以拆成三个可复用的部分哈希表管理连接、序列号比较和乱序队列、缓冲区管理。如果只需要 TCP 重组不需要 IDS 功能可以把这三部分抽出来去掉 libnids 的会话管理和回调框架代码量能减少一半以上。模块libnids 中的位置可复用程度注意事项连接哈希表session.c/tcp.c高需要自己处理超时清理序列号比较tcp.c宏定义高直接复制注意平台溢出行为乱序队列tcp.c半连接结构中需要根据内存预算调大小分片重组ip_fragment.c中如果只处理 TCP 可以去掉回调框架nids.c低通常用自己的事件循环替代表格说明可复用程度“高”表示几乎可以直接搬“中”表示需要改参数或裁剪“低”表示建议重写。注意事项里写的是搬运时最容易出问题的地方。最后说一个我自己的习惯读 libnids 这类中间层源码时我会先画一张状态流转图纸上画不写进代码把每个状态和触发条件标出来然后再对照代码加注释。这样注释不是逐行翻译而是对状态机的标注。另一个习惯是每加完一个模块的注释就用 gdb 跑一遍确认注释里写的“应该怎样”和实际行为一致。不一致的地方要么是注释错了要么是代码有隐藏逻辑都是值得深挖的点。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

ESP32-S3开发板深度解析:双核架构、原生USB与AI边缘部署实战

ESP32-S3开发板深度解析:双核架构、原生USB与AI边缘部署实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/20 1:29:10
DeepSeek-V3技术报告精读:MLA、MoE和MTP复现要义

DeepSeek-V3技术报告精读:MLA、MoE和MTP复现要义

简介:《DeepSeek-V3技术报告》PDF完整收录DeepSeek-AI最新混合专家(MoE)语言模型原始论文,面向大模型研究者、算法工程师及深度学习爱好者,重点阐述6710亿总参数、370亿激活参数的MoE架构,及多头潜在注意力…

📅 2026/10/20 1:29:10
基于STM32、华为云IoT与Qt的智能家居远程控制系统实现

基于STM32、华为云IoT与Qt的智能家居远程控制系统实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/20 1:29:10
MORE NEWS

更多资讯

📰

CNN人脸识别从零搭建:数据清洗到模型推理全流程实战指南

简介:这是一份面向深度学习初学者与计算机视觉入门者的卷积神经网络人脸识别实战代码,以经典人脸数据集为对象,系统演示从数据预处理、网络构建到模型训练与测试的完整流程。压缩包共含四个文件,其中两个可执行脚本分别完成模型训…

📰

FreeRTOS从裸机到实战:任务调度、内存管理与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

SPI屏嵌入式信息面板实战:从接线到点亮,跑通第一个系统状态Demo

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

MCAL功能安全分析实战:失效模式、诊断覆盖率与故障注入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

50步还是8步?MOSS-Image-Base-bf16采样参数完全指南:Euler Flow Matching、CFG与Shift调优

人工智能大模型基础模型媒体生成本地部署 【免费下载链接】MOSS-Image-Base-bf16 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/MOSS-Image-Base-bf16 点击查看 免费下载 MOSS-Image-Base-bf16 是面向 Apple Silicon 的 MLX bf16 文生图扩散模型。它…

📰

GGUF 量化原理新手详解:Ling-3.0-tiny-GGUF 的 Q4_K_M 如何以 4.8GB 保全心智

【免费下载链接】Ling-3.0-tiny-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/inclusionAI/Ling-3.0-tiny-GGUF 点击查看 免费下载 这篇文章用小白也能看懂的方式,讲清 GGUF 量化原理:Ling-3.0-tiny-GGUF 是一个 7.9B 总参数、每 toke…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬