深入理解 Linux 阻塞IO与Socket数据结构
一、阻塞IO的直观演示
示例代码:最简单的阻塞接收程序
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>int main() {// 创建TCP套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);// 绑定地址端口struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8080);addr.sin_addr.s_addr = INADDR_ANY;bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));// 开始监听listen(sockfd, 5);printf("等待客户端连接...\n");// 阻塞点1:接受连接struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &len);printf("客户端已连接!\n");// 阻塞点2:接收数据char buf[1024];int ret = recv(clientfd, buf, sizeof(buf), 0);printf("收到数据:%s\n", buf);close(clientfd);close(sockfd);return 0;
}
以下是等效的 Java 版本实现,保留了阻塞 IO 的特性并添加了详细注释:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class BlockingIOServer {public static void main(String[] args) {// 创建TCP套接字并绑定端口(对应C的socket+bind+listen)try (ServerSocket serverSocket = new ServerSocket(8080)) {System.out.println("等待客户端连接...");// 阻塞点1:接受客户端连接(对应C的accept)Socket clientSocket = serverSocket.accept();System.out.println("客户端已连接!");// 阻塞点2:接收数据(对应C的recv)InputStream inputStream = clientSocket.getInputStream();byte[] buffer = new byte[1024];// read()方法会阻塞直到有数据到达int bytesRead = inputStream.read(buffer); System.out.println("收到数据:" + new String(buffer, 0, bytesRead));// 自动关闭资源(Java 7+ try-with-resources)} catch (IOException e) {e.printStackTrace();}}
}
其实本质上java的代码和C语言代码是一样的,都是调用对应的系统函数。
阻塞行为分析
accept()
调用阻塞:直到有客户端连接才会继续执行recv()
调用阻塞:当连接建立后,如果客户端不发送数据,进程会一直挂起
二、Socket全生命周期
2.1 创建阶段:从用户态到内核态的旅程
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
流程详解(附内核调用链):
用户空间调用 socket()
↓
系统调用 sys_socket() → 陷入内核
↓
sock_create() → 创建通用socket对象
↓
查找协议族 net_families[AF_INET] → 获取IPv4协议族操作表
↓
调用 inet_create() → 创建TCP/UDP专用socket
│ ↓
分配 struct sock 结构 → 初始化连接状态为 TCP_CLOSE
↓
注册协议操作函数 → 设置 tcp_prot(TCP协议处理引擎)
↓
关联文件描述符 → 通过 file_operations 绑定读写方法
关键步骤深度解析:
-
协议族选择
// net/socket.c static int __init sock_init(void) {// 初始化时注册协议族rc = netlink_kernel_create(&init_net, NETLINK_ROUTE, ...);rc = inet_add_protocol(&icmp_protocol, IPPROTO_ICMP);... }
net_families[AF_INET]
指向ipprot
结构,包含IPv4协议处理函数
-
传输层协议绑定
// net/ipv4/af_inet.c int inet_create(struct net *net, struct socket *sock, int protocol) {// 根据协议类型选择处理引擎if (protocol == IPPROTO_TCP)sock->ops = &inet_stream_ops; // TCP操作集else if (protocol == IPPROTO_UDP)sock->ops = &inet_dgram_ops; // UDP操作集// 分配TCP专用数据结构sk = sk_alloc(net, PF_INET, GFP_KERNEL, &tcp_prot, 0); }
-
资源预分配
- 预分配接收队列缓存:
sk->sk_receive_queue
(基于内存池的sk_buff分配) - 初始化等待队列:
sk->sk_sleep
(后续阻塞操作的基础设施)
- 预分配接收队列缓存:
2.2 连接建立阶段:TCP三次握手的微观视角
connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
状态转换全景图:
TCP_CLOSE → TCP_SYN_SENT → TCP_ESTABLISHED↑ ↑ ↑SYN SYN-ACK ACK
内核处理流水线:
用户调用 connect()
↓
tcp_connect() → 设置状态为 TCP_SYN_SENT
↓
生成SYN报文 → 调用 ip_queue_xmit() 发送
↓
进入状态机等待 → sk->sk_state = TCP_SYN_SENT
↓
等待ACK到达 → 触发 sk_state_change 回调
关键机制详解:
-
SYN报文发送
// net/ipv4/tcp_output.c int tcp_connect(struct sock *sk) {// 构建SYN报文struct sk_buff *skb = alloc_skb(sizeof(struct tcphdr) + ...);tcp_init_nondata_skb(skb, tcp_current_seq(sk), TCPHDR_SYN);// 发送队列管理skb_queue_tail(&sk->sk_write_queue, skb);ip_queue_xmit(sk, NULL, skb); }
-
等待队列机制
// 当前进程进入等待状态 set_current_state(TASK_INTERRUPTIBLE); add_wait_queue_exclusive(&sk->sk_sleep, &wait);while (sk->sk_state != TCP_ESTABLISHED) {if (signal_pending(current))return -EINTR;schedule(); }
-
状态机驱动
// net/ipv4/tcp_states.h static const struct tcp_state_trans tcp_established_transitions = {.transitions = {[TCP_ESTABLISHED] = {.event = TCP_EARLY_DATA,.next_state = TCP_ESTABLISHED,.action = tcp_rcv_established,},// 处理ACK包的回调注册}, };
阻塞行为本质:
当调用 connect()
时:
- 若端口不可用/连接被拒绝 → 立即返回错误
- 若正常发送SYN → 进程进入
TASK_UNINTERRUPTIBLE
等待 - 当收到SYN-ACK后 → 内核完成握手 → 触发
sk->sk_data_ready
- 最终唤醒进程 → 返回成功
2.3 生命周期全景图
各阶段内存管理:
- 创建阶段:预分配接收缓冲区(
sk->sk_rmem_alloc
) - 传输阶段:动态调整发送窗口(
sk->snd_wnd
) - 关闭阶段:释放关联的skb队列
三、核心数据结构详解
3.1 socket结构体家族树
struct socket
├── struct file (VFS层对象)
└── struct sock (协议无关层)├── struct tcp_sock (TCP协议私有数据)└── struct udp_sock (UDP协议私有数据)
具体解释见下面
3.2 关键数据结构详解
3.2.1 struct socket:用户态与内核态的桥梁
struct socket {const struct proto_ops *ops; // 协议操作函数表(TCP/UDP/SCTP等)struct sock *sk; // 核心协议栈对象(传输层控制块)struct file *file; // 关联的文件描述符(VFS接口)
};
核心功能解析:
- ops指向协议族操作表(如inet_stream_ops),代码如下:
const struct proto_ops inet_stream_ops = {.family = PF_INET,.recvmsg = inet_recvmsg, // 接收消息入口.sendmsg = inet_sendmsg, // 发送消息入口.accept = inet_accept, // 接受新连接.bind = inet_bind, // 绑定端口...
};
通过函数指针实现协议无关接口,支持多协议扩展,类比Java接口实现:就像Java中DataSource接口可以有不同的实现类(MySQL/Oracle),C语言通过proto_ops函数指针数组实现协议多态。当用户调用read()系统调用时,最终会通过socket->ops->recvmsg调用具体协议的接收函数。例如udp协议的接收消息,这里的recvmsg会指向udp的接收实现,如果是tcp协议,recvmsg那么就指向tcp的接收实现(经过三次握手后,可以接收消息)。
- *sk,核心协议栈对象,下面会有解释,此处略
- *file,关联的文件描述符,file指针将socket映射到文件系统,实现read()/write()等文件操作语义
3.2.2 struct sock
struct sock {const struct proto *sk_prot; // 协议处理函数(如 tcp_prot)struct sk_buff_head sk_receive_queue; // 接收队列wait_queue_head_t sk_sleep; // 进程等待队列头 sk_wqvoid (*sk_data_ready)(struct sock *sk); // 数据就绪通知回调// ...其他字段
};
- 协议处理引擎 sk_prot
// TCP协议处理结构体
struct proto tcp_prot = {.name = "TCP",.err_handler = tcp_err, // 错误处理.recvmsg = tcp_recvmsg, // 数据接收(含流量控制).sendmsg = tcp_sendmsg, // 数据发送(含拥塞控制)//...其它字段
};
工作流程示例:当应用层调用send()
时,数据会经过以下路径:
用户空间缓冲区 → socket->ops->sendmsg → tcp_sendmsg → 协议栈处理 → 驱动程序发送
- 接收队列 sk_receive_queue,即网络数据包
- 等待队列 sk_sleep,阻塞行为本质:当接收队列为空时,进程会被挂入
sk_sleep
队列,直到有数据到达触发唤醒。 sk_data_ready
负责在数据就绪时触发进程唤醒,是阻塞IO模型的核心机制。具体看下文。
四、阻塞IO唤醒机制
4.1 sk_data_ready
的本质
定义:
sk_data_ready
是 struct sock
中定义的一个函数指针,其类型为 void (*sk_data_ready)(struct sock *sk)
。它是 协议栈向应用层传递数据就绪通知的核心机制,所有传输层协议(TCP/UDP)都需要实现此回调。
代码定位:
// net/core/sock.h
struct sock {...void (*sk_data_ready)(struct sock *sk); // 数据就绪通知回调...
};
4.2 工作流程:从网卡到应用层
以下是 sk_data_ready
被触发的完整链路(以TCP为例):
graph TDA[网卡接收数据包] --> B[硬件中断]B --> C[软中断(napi_schedule)]C --> D[napi_poll处理]D --> E[ip_rcv() → tcp_v4_rcv()]E --> F[协议处理(tcp_rcv)]F --> G[调用sk_data_ready(sk)]G --> H[唤醒等待队列(sk_sleep)]H --> I[应用层recv()返回数据]
关键步骤解析:
- 中断阶段:网卡收到数据包触发硬件中断,注册的中断处理函数标记
NAPI
结构体。 - 软中断阶段:内核的
ksoftirqd
线程执行napi_poll()
,开始处理接收队列。 - 协议栈处理:数据包经过IP层、TCP层解析,最终进入
tcp_v4_rcv()
。 - 触发回调:在协议处理完成后,内核调用
sk->sk_data_ready(sk)
。 - 唤醒进程:
sk_data_ready
的默认实现会调用sk_wake_async()
,最终通过wake_up_interruptible(&sk->sk_sleep)
唤醒等待队列中的进程。
4.3、sk_data_ready
与阻塞IO的阻塞/唤醒机制
4.3 1. 阻塞IO的核心逻辑
当应用层调用阻塞型 recv()
时:
// 系统调用入口 sys_recvfrom
if (skb_queue_empty(&sk->sk_receive_queue)) {// 数据未就绪,进程进入睡眠set_current_state(TASK_INTERRUPTIBLE);add_wait_queue(&sk->sk_sleep, &wait);schedule(); // 主动让出CPUremove_wait_queue(...);
}
4.3.2. sk_data_ready
的触发时机
- 数据就绪时:当
sk_data_ready
被调用时,会触发以下动作:// 默认实现(net/core/sock.c) static inline void sock_def_readable(struct sock *sk, int len) {if (!sock_flag(sk, SOCK_DEAD)) {// 唤醒所有在sk_sleep队列中等待的进程wake_up_interruptible(&sk->sk_sleep);// 触发异步通知(如信号)sk_wake_async(sk, SOCK_WAKE_IO, POLL_IN);} }
4.3.3. 阻塞IO的唤醒本质
- 等待队列(Wait Queue):进程在调用阻塞型
recv()
时会被加入sk->sk_sleep
队列,并设置为不可中断状态(TASK_INTERRUPTIBLE
)。 - 唤醒条件:只有当
sk_data_ready
被调用时,才会触发队列唤醒。这意味着:- 数据必须通过协议栈处理完成(如TCP三次握手完成、数据包校验通过)。
- 内核协议栈确认数据已准备好被用户空间读取。
总结
通过本文的学习,你应该已经掌握:
- 阻塞IO的底层行为模式
- Socket从创建到数据传输的完整生命周期
- 核心数据结构(socket/sock/sk_buff)的协作关系
- 系统调用到内核处理的完整链路
参考文档
- 深入理解Linux网络: 修炼底层内功,掌握高性能原理 (张彦飞)
相关文章:
深入理解 Linux 阻塞IO与Socket数据结构
一、阻塞IO的直观演示 示例代码:最简单的阻塞接收程序 #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h>int main() {// 创建TCP套接字int sockfd socket(AF_INET, SOCK_STREAM, 0);// 绑定地址端口struct sockaddr_in ad…...
大模型系列(三)--- GPT1论文研读
论文链接: GPT1: Improving Language Understanding by Generative Pre-Training 点评: 首次将Transformer的decoder部分引入无监督训练且引入了辅助训练目标。文章证明无监督预训练显著提升判别任务性能,其中Transformer架构和长依赖文本数…...
14.Three.js 中的 SpotLight(聚光灯)详解与 Vue3 实战示例
在 Three.js 中,SpotLight(聚光灯)是一种能沿着一个方向发射锥形光束的光源,广泛应用于舞台灯光、聚焦灯、手电筒等模拟场景中。本文将详细介绍 SpotLight 的各个属性和使用方法,并提供一个基于 Vue3 Composition API…...
unix 详解
Unix 系统深度解析 一、Unix 起源与历史 Unix 是由 贝尔实验室(AT&T Bell Labs) 的 肯汤普森(Ken Thompson) 和 丹尼斯里奇(Dennis Ritchie) 于 1969 年 开发的操作系统。其诞生背景是: …...
NetSuite 常用类型Item对应Account异同
NetSuite中会有多种类型不同的Item,在期初数据收集的时候我们一般也会让用户提供给我们Item的主数据信息,其中就包含科目部分,但不同类型Item对应科目不完全相同,所以就想帮助自己和各位一起来梳理一下相关内容。 一般我们常用It…...
CentOS配置了镜像源之后依旧下载元数据失败
// 切换到root用户 su root备份原有的镜像源 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup使用阿里云镜像源 sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo这是清华的…...
mybatis 的多表查询
文章目录 多表查询一对一一对多 多表查询 一对一 开启代码片段编写 专注于 SQL的 编写 JDBC 的写法,注重于 SQL mybatis 在 一对一查询时,核心在于 建立每个表对应的实体类主键根据 主键 id 进行查询,副标根据 设定外键进行查询 在 SQL编写…...
面试常问系列(一)-神经网络参数初始化-之自注意力机制为什么除以根号d而不是2*根号d或者3*根号d
首先先罗列几个参考文章,大家之后可以去看看,加深理解: 面试常问系列(一)-神经网络参数初始化面试常问系列(一)-神经网络参数初始化之自注意力机制_注意力机制的参数初始化怎么做-CSDN博客面试常问系列(一)-神经网络参数初始化-之-softmax-C…...
Linux服务之nginx中http设置及虚拟主机搭建
目录 一.http相关概述 1.mime 2.server下的listen及root 2.1 listen 2.2 root 3.alias别名 4.location相关概述 4.1 语法规则初步解释 5.access模块 6.验证模块 6.1 htpasswd 7.自定义错误页面 8.虚拟主机搭建 (yum安装) 一.http相关概述 h…...
android-ndk开发(7): 从库文件反推ndk版本
android-ndk开发(7): 从库文件反推ndk版本 2025/05/06 1. 概要 对于动态库, 有些能用 parse_elfnote.py 提取,有些不能。 对于静态库, 不能用 parse_elfnote.py 提取; 对于 libopencv_core.a, 可以搜索关键字 General configu…...
MySQL8查询某个JSON类型的字段中出现过的所有键名(json key name)并去重返回
假设我有一张表叫 t1, 其中有一个字段 info 是 JSON类型,现在我想查询 t1.info 字段中出现过的所有键名,MySQL提供了一个函数 JSON_KEYS(column) 来返回单条数据单个JSON字段中的所有键名组成的集合,那我想查询整个表所有记录中某个JSON字段出…...
【AI】基于生活案例的LLM强化学习(入门帖)
一、从“教小孩说话”到“教模型说话”:LLM 训练全貌 1. 先打个比方 第一阶段:预训练 就好比教一个小孩先“读很多书”,让他获得基本的语言能力。对 LLM 来说,就是在海量文本上进行“预测下一个词”的训练,从而学到“…...
如何通过代理 IP 实现异地直播推流
在直播行业日益火爆的今天,许多主播希望突破地域限制,实现异地直播推流,以获得更广泛的观众群体和更好的直播效果。代理 IP 作为一种有效的网络工具,能够帮助主播轻松达成这一目标。本文将详细介绍如何通过代理 IP 实现异地直播推…...
Linux 网络编程 day5 多路IO转接之改进select and poll
三种多路IO转接方法:select , poll , epoll 改进select多路IO转接,使用数组来保存含有需要连接的套接字cfd,不用循环至1024,节约时间提高效率。 #include<stdio.h> #include<stdlib.h> #in…...
【iOS】源码阅读(二)——NSObject的alloc源码
文章目录 前言问题发现探索NSObject的alloc源码实现流程探索NSObject为什么直接走objc_alloc,而GGObject先走alloc总结 前言 前面笔者已经学习了alloc相关源码,之前的alloc底层源码实现步骤是以GGObject为基础的,今天我们来探索一下NSObject中…...
如何在短时间内高效复习食品安全员考试?
以下是一些在短时间内高效复习食品安全员考试的方法: 制定科学计划:根据剩余时间和考试内容,将备考时间划分为基础学习、强化巩固和模拟冲刺三个阶段。如基础学习阶段可安排每天学习 2-3 小时,梳理教材知识;强化巩固阶…...
Kotlin空安全解决Android NPE问题
在 Android 开发中,NullPointerException(NPE)一直是最常见的崩溃类型之一。Kotlin 通过创新的空安全机制,在语言层面彻底解决了这一问题。以下是 Kotlin 空安全的核心要点和实战指南: 一、Kotlin 空安全设计哲学 编译期防御:通过类型系统强制区分可空(?)与非空类型显…...
PrimExpr 与 RelayExpr 的区别
PrimExpr 与 RelayExpr 的区别解析 在 TVM 的表达式系统中,PrimExpr 和 RelayExpr 是两种不同层级的表达式类型,分别服务于 TVM 的不同编译阶段和目标场景。以下是它们的核心区别和关联: 1. 设计目标与层级 特性PrimExprRelayExpr所属层级TV…...
R语言助力森林生态研究:从数据处理到群落稳定性分析的完整流程,结合机器学习与案例写作
在生态学研究中,森林生态系统的结构、功能与稳定性是核心研究内容之一。这些方面不仅关系到森林动态变化和物种多样性,还直接影响森林提供的生态服务功能及其应对环境变化的能力。 👉 森林生态系统的结构、功能与稳定性是生态学研究的核心。…...
android-ndk开发(8): ndk 和 clang 版本对照表
android-ndk开发(8): ndk 和 clang 版本对照表 2025/05/06 1. 概要 android-ndk 是基于 clang 的编译工具链。 当 clang 自身的版本变更导致了普通用户的编译、链接报错时, 用户可能只关注到了 ndk 版本, 导致问题的分析浮于表面。 android-ndk 官方…...
《AI大模型应知应会100篇》第50篇:大模型应用的持续集成与部署(CI/CD)实践
第50篇:大模型应用的持续集成与部署(CI/CD)实践 🧾 摘要 在AI大模型开发中,随着模型版本迭代频繁、依赖复杂、部署环境多样,构建一套高效可靠的持续集成与持续交付(CI/CD)流程显得尤…...
Python基于Django的在线考试系统【附源码、文档说明】
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
windows操作系统开机自启(自动启动) 运行窗口 shell:startup 指令调出开机自启文件夹
打开 “运行” 窗口,输入 shell:startup 把需要开机自启程序的快捷启动方式复制到启动文件夹 (注意:一定要复制快捷启动方式,可以右键启动的文件,发送到桌面快捷方式,如果直接把启动的文件放进去ÿ…...
笔记本外接显示器检测不到hdmi信号
原因:AMD显卡驱动挂了。 其他 异常特征:显示亮度被禁用,无法调整。 修复步骤: ① ②点击更新驱动程序...
论软件的可靠性设计
目录 摘要(300~330字) 正文(2000~2500字,2200字为宜) 背景介绍(500字做左右) 论点论据(1500字做左右)...
【Linux】基础开发工具
L i n u x Linux Linux 环境下的开发工具非常丰富,是程序员和开发人员进行高效开发的必备基础。 L i n u x Linux Linux 环境下的开发工具主要包括 y u m yum yum 软件包管理器、 v i m vim vim 文本编辑器、 g c c / g gcc/g gcc/g 编译器、 g d b gdb gdb 调试工…...
【编程干货】本地用 Ollama + LLaMA 3 实现 Model Context Protocol(MCP)对话服务
模型上下文协议(MCP)本身提供的是一套标准化的通信规则和接口,简化了客户端应用的开发。 MCP 实际上是一套规范,官方把整套协议分成「传输层 协议层 功能层」三大块,并对初始化握手、能力协商、数据/工具暴露、安全…...
华为策略路由
路由策略:是对路由条目进行控制,通告控制路由条目影响报文的转发路径。路由策略为控制平面。 策略路由:是根据报文特征,认为的控制报文从某个即可转发出去,不修改路由表。即策略路由为在转发平面。 路由策略 策略路由…...
Spring Boot3 实现定时任务 每10分钟执行一次,同时要解决分布式的问题 区分不同场景
在Spring Boot 3中实现分布式定时任务,确保多实例环境下任务仅执行一次,可以采用以下方案: 方案一:Redis分布式锁(推荐) import org.springframework.data.redis.core.StringRedisTemplate; import org.sp…...
山东大学项目实训-创新实训-法律文书专家系统-项目报告(四)
项目简介 法律文书专家系统是一个 Web 应用,提供法律文书摘要提取、法律预测报告生成和法律考试问题答疑三大核心功能。用户需要登录或注册后,进入主页面选择所需功能,进行相应的操作。 用户群体 律师:需要快速提取法律文书摘要…...
sqli-labs靶场通关保姆级教学(Get传输篇)Less-1Less-10
sqli-labs靶场通关保姆级教学(Get传输篇)Less-1~Less-10(纯手注) sqli - labs 靶场是一个专门用于网络安全学习和测试 SQL 注入漏洞的开源靶场。包含报错盲注、布尔盲注、基于联合查询的 SQL 注入等多种类型的 SQL 注入漏洞&…...
Day17 聚类算法(K-Means、DBSCAN、层次聚类)
一、聚类算法 1. K-Means 聚类 原理:K-Means 是一种基于划分的聚类算法,目标是将 n n n 个样本划分到 k k k 个簇中,使得簇内样本的相似度尽可能高,簇间样本的相似度尽可能低。算法通过迭代的方式,不断更新簇的质心…...
构建 Web 浏览 AI Agent:Pydantic + MCP 实现指南
在当今快节奏的数字世界中,高效地从网站提取和总结信息可以成为改变游戏规则的利器。大型语言模型(LLM)提供了令人难以置信的能力,但它们本身并不知道如何浏览网络或获取实时内容。 本文演示如何创建一个由Python驱动的AI Agent,它能够阅读和总结网站内容,使其成为研究人员…...
解决 pnpm dev 运行报错的坎坷历程
解决 pnpm dev 运行报错的坎坷历程 在项目开发过程中, 在clone完别人的代码后启动项目时:nodejs 和 pnpm版本都没问题 ,但是 无法运行 pnpm dev 命令启动项目时,往往会遇到各种各样的报错问题。最近在处理 yudao-ui-admin-vue3 项…...
从贴牌到品牌:出海官网如何让中国制造“贵”起来?
在全球经济一体化的当下,中美关税战如同一记重锤,给国际贸易格局带来了巨大震荡。自贸易摩擦爆发以来,双方多次调整关税政策,涉及的商品种类不断增多,税率持续攀升,众多中国企业的出口业务遭受重创…...
ultralytics框架进行RT-DETR目标检测训练
自DETR提出以来,其采用匈牙利匹配方式真正的实现了端到端检测效果,避免了NMS等后处理过程,同时,相较CNN的局部特征提取,其凭借着Transformer强大的全局特征提取能力,在目标检测领域可谓大杀四方,…...
SQLite基本函数
目录 1 核心函数和聚合函数 1.1 核心函数 1.2 聚合函数 2 字符串函数 3 日期和时间函数 4 数学函数 5 JSON函数 (SQLite 3.9.0) 6 窗口函数 (SQLite 3.25.0) 7 加密和安全函数 8 其他实用函数 9 C#代码示例:使用SQLite函数 9.1 准备工作 9.2 代码实现…...
使用Java和LangChain4j实现人工智能:从分类到生成式AI
人工智能(AI)从科幻小说中的梦想逐步演变为现实,驱动了从语音助手到自动驾驶汽车的各种应用。AI 的发展主要基于两种方法:基于编码的传统方法和基于机器学习的现代方法。机器学习通过神经网络和大量训练数据实现分类、生成等任务&…...
数据分析指标体系
目录 1. 构建业务公式,用量化逻辑串联业务 1.1 明确公式结果 1.2 拆解业务过程 1.3 构建计算关系(yaxb) 经典的成交额业务公式 小疑问: 如何让自己的指标看起来更专业? 量化业务过程的量化,到底是什…...
分布式、高并发-Day04
以下是 Day 4 详细学习内容(CAS 与原子操作实战,30 分钟完整计划),包含原理解析、分步代码实战和性能对比: 📖 今日学习目标 掌握 CAS(Compare-And-Swap)无锁算法的核心原理学会使…...
计算机中的逻辑运算
目录 一、总览 二、详情 1. 基本逻辑运算(与、或、非): 2. 其他常用的逻辑运算(异或、同或、与非、或非): 在计算机中,逻辑运算是构成数字电路和计算机程序基础的关键操作。它们处理的是真值…...
Dify - Stable Diffusion
Stable Diffusion 是一种基于文本提示生成图像的工具,Dify 已经实现了访问 Stable Diffusion WebUI API 的接口,因此你可以直接在 Dify 中使用它。以下是在 Dify 中集成 Stable Diffusion 的步骤。 1. 初始化本地环境 推荐使用装有较强 GPU 的机器来安…...
weapp-vite - 微信小程序工具链的另一种选择
weapp-vite - 微信小程序工具链的另一种选择 前言 weapp-vite 是由 笔者 icebreaker 开发的一个基于 vite 的现代化微信小程序开发工具链。我给它设定的目标初心是: 为小程序开发者带来笑容。 自从在 2024 年的 8 月正式发布之后,到现在也过了将近 9 个月的时间。…...
图形化编程重塑 IoT 边缘开发:技术革新与生态竞合新范式
本文以图形化编程技术为核心,深度剖析其在 IoT 边缘开发中的创新应用与行业变革。通过对传统开发困局的系统解构,结合 iVX 项目等典型案例,揭示图形化编程如何通过可视化逻辑设计、自动代码生成及 AI 驱动架构,实现开发效率与应用…...
node-sass安装失败解决方案
1、python环境问题 Error: Cant find Python executable "python", you can set the PYTHON env variable. 提示找不到python2.7版本, 方法一:可安装一个python2.7或引用其他已安装的python2.7 通过设置环境变量可以解决; 方法二&…...
PDF内容搜索--支持跨文件夹多文件、组合词搜索
平时我们接触到的PDF文档特别多,需要对PDF文档做一些处理,那么今天给大家带来的这两个软件非常的棒,可以帮你提升处理文档的效率。 PDF内容搜索 快速检索 我用夸克网盘分享了「PDF搜索PDF 转长图.zip」,点击链接即可保存。打开「…...
我用cursor 搭建了临时邮箱服务-Temp Mail 365
用业余时间搭建了一个临时邮箱,对于后端程序员出身的我,对前端了解的不太多,有了cursor的帮助,补齐了自己的短板,搭建了这个服务,下面对临时邮箱架构设计与安全性做一个分析。 https://temp-mail-365.com 临…...
RN学习笔记 ✅
太无聊了最近,找点事做,学一下RN丰富一下技术栈🫡。但是开发APP除了RN,还有一种选择就是WebView,但是基于WebView的APP的性能被普遍认为不如RN,因为WebView本质上是一个容器,用于在应用中嵌入网…...
使用原生 CSS 实现轮播
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、核心新特性1. ::scroll-button()2. ::scroll-marker()二、基础实现步骤1. 创建滚动容器2. 添加滚动按钮3. 集成滚动标记三、高级功能1. 滚动驱动动画2. 状态查询3. 响应式布局四、展示前言 最新!原生CSS也可以实现轮播…...
C语言进阶—函数(static,递归,回调,指针,内联,变参,结构体尺寸)
目录 一 static函数 1. static变量 1.静态局部变量 2.静态全局变量 2. static函数 二 递归函数 三 指针函数&函数指针 1. 指针函数 2. 函数指针 四 回调函数 五 内联函数 1. 核心特性表 2. 优缺点分析表 3. 用场景建议 3.1 推荐使用场景 3.2 应避免场景 六…...