Linux阻塞与非阻塞I/O:从原理到实践详解
Linux阻塞与非阻塞I/O:从原理到实践详解
1. 阻塞与非阻塞I/O基础概念
1.1 阻塞与非阻塞简介
在Linux系统编程中,I/O操作可以分为两种基本模式:阻塞I/O和非阻塞I/O。这两种模式决定了当设备或资源不可用时,程序的行为方式。
阻塞I/O就像你在餐厅点餐后坐在座位上等待服务员上菜。在此期间你不能做其他事情,只能等待食物送到面前。在编程中,这意味着当程序执行I/O操作时,如果数据未准备好,进程会进入睡眠状态,直到条件满足才会继续执行。
非阻塞I/O则像是自助餐厅的就餐方式。你拿着餐盘去取食物,如果某个菜品暂时没有,你不会站在那里等待,而是先去拿其他食物,过一会儿再来查看。在编程中,这意味着当I/O操作无法立即完成时,操作会立即返回一个错误码(如EAGAIN),而不会阻塞进程。
代码示例对比:
// 阻塞方式读取串口
fd = open("/dev/ttyS1", O_RDWR);
read(fd, &buf, 1); // 串口有输入才返回// 非阻塞方式读取串口
fd = open("/dev/ttyS1", O_RDWR | O_NONBLOCK);
while(read(fd, &buf, 1) != 1) continue; // 循环尝试读取
1.2 两种模式的优缺点
阻塞I/O的优点:
- CPU利用率高,因为等待时不占用CPU资源
- 编程模型简单直接
- 适合顺序处理任务
阻塞I/O的缺点:
- 响应性差,无法同时处理多个I/O操作
- 可能导致进程长时间挂起
非阻塞I/O的优点:
- 响应性好,可以同时监控多个I/O操作
- 进程不会被长时间挂起
- 适合高并发场景
非阻塞I/O的缺点:
- CPU利用率高,因为需要不断轮询
- 编程复杂度较高
- 可能导致忙等待(busy waiting)
2. 等待队列机制
2.1 等待队列的概念
等待队列是Linux内核中实现阻塞I/O的核心机制。它允许进程在条件不满足时进入睡眠状态,当条件满足时再被唤醒。这就像医院候诊室的叫号系统,病人(进程)可以坐着休息(睡眠),当轮到他们时会被叫醒(唤醒)。
2.2 等待队列的操作接口
- 定义和初始化等待队列头:
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);
// 或者使用宏一次性完成
DECLARE_WAIT_QUEUE_HEAD(my_queue);
- 定义等待队列项:
DECLARE_WAITQUEUE(name, tsk); // tsk一般为current表示当前进程
- 添加/移除等待队列:
add_wait_queue(&my_queue, &wait); // 添加
remove_wait_queue(&my_queue, &wait); // 移除
- 等待事件:
wait_event(wq, condition); // 无条件等待
wait_event_timeout(wq, condition, timeout); // 带超时等待
wait_event_interruptible(wq, condition); // 可被信号中断的等待
- 唤醒队列:
wake_up(&queue); // 唤醒所有等待的进程
wake_up_interruptible(&queue); // 只唤醒可中断的进程
2.3 等待队列的使用模板
一个典型的驱动中使用等待队列的模板如下:
static ssize_t device_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{DECLARE_WAITQUEUE(wait, current);add_wait_queue(&dev->read_queue, &wait);// 等待数据可用while (data_not_ready()) {if (file->f_flags & O_NONBLOCK) { // 非阻塞模式检查remove_wait_queue(&dev->read_queue, &wait);return -EAGAIN;}__set_current_state(TASK_INTERRUPTIBLE);schedule(); // 让出CPUif (signal_pending(current)) { // 检查是否有信号remove_wait_queue(&dev->read_queue, &wait);return -ERESTARTSYS;}}// 数据已准备好,进行读取操作copy_to_user(buffer, dev->data, count);remove_wait_queue(&dev->read_queue, &wait);set_current_state(TASK_RUNNING);return count;
}
3. 轮询机制
3.1 轮询的概念
对于非阻塞I/O,当操作不能立即完成时,应用程序需要通过轮询的方式不断检查设备是否就绪。这就像你等待快递时不断查看物流信息,而不是坐在门口一直等待。
3.2 常见的轮询机制
- select系统调用:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select使用位图(fd_set)来表示文件描述符集合,有以下操作宏:
FD_ZERO(fd_set *set); // 清空集合
FD_SET(int fd, fd_set *set); // 添加描述符
FD_CLR(int fd, fd_set *set); // 移除描述符
FD_ISSET(int fd, fd_set *set); // 检查描述符
- poll系统调用:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
poll使用动态数组而非固定大小的位图,没有文件描述符数量限制。pollfd结构体定义如下:
struct pollfd {int fd; // 文件描述符short events; // 等待的事件short revents; // 实际发生的事件
};
- epoll机制:
epoll是为处理大并发而设计的更高效的机制,使用红黑树管理文件描述符,避免了select/poll的线性扫描问题。
3.3 轮询机制的选择
- 少量文件描述符:select或poll都可以
- 大量文件描述符:优先选择epoll
- 跨平台需求:select兼容性最好
- 精确事件通知:poll或epoll更合适
4. 驱动中的poll操作函数
4.1 poll操作函数的作用
在Linux驱动中,poll操作函数用于支持select/poll系统调用,它需要完成两个主要任务:
- 将当前文件描述符加入适当的等待队列
- 返回设备当前的状态掩码
4.2 poll函数的实现模板
static unsigned int device_poll(struct file *filp, poll_table *wait)
{struct device_data *dev = filp->private_data;unsigned int mask = 0;poll_wait(filp, &dev->read_queue, wait);poll_wait(filp, &dev->write_queue, wait);if (data_available(dev)) // 检查是否可读mask |= POLLIN | POLLRDNORM;if (space_available(dev)) // 检查是否可写mask |= POLLOUT | POLLWRNORM;return mask;
}
4.3 poll支持的事件标志
POLLIN
:有普通或优先级带数据可读POLLRDNORM
:有普通数据可读POLLRDBAND
:有优先级带数据可读POLLPRI
:有高优先级数据可读POLLOUT
:写数据不会导致阻塞POLLWRNORM
:写普通数据不会导致阻塞POLLWRBAND
:写优先级带数据不会导致阻塞POLLERR
:发生错误POLLHUP
:设备已断开连接POLLNVAL
:文件描述符未打开
5. 阻塞I/O实验:实现一个FIFO设备驱动
5.1 实验目标
实现一个支持阻塞读写的全局FIFO设备驱动:
- 当FIFO为空时,读进程阻塞
- 当FIFO满时,写进程阻塞
- 支持select/poll监控
5.2 关键数据结构
#define FIFO_SIZE 4096struct globalfifo_dev {struct cdev cdev;unsigned int current_len;unsigned char mem[FIFO_SIZE];struct mutex mutex;wait_queue_head_t read_wait;wait_queue_head_t write_wait;
};
5.3 读函数实现
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{struct globalfifo_dev *dev = filp->private_data;DECLARE_WAITQUEUE(wait, current);int ret = 0;mutex_lock(&dev->mutex);add_wait_queue(&dev->read_wait, &wait);while (dev->current_len == 0) {if (filp->f_flags & O_NONBLOCK) {ret = -EAGAIN;goto out;}__set_current_state(TASK_INTERRUPTIBLE);mutex_unlock(&dev->mutex);schedule();if (signal_pending(current)) {ret = -ERESTARTSYS;goto out2;}mutex_lock(&dev->mutex);}if (count > dev->current_len)count = dev->current_len;if (copy_to_user(buf, dev->mem, count)) {ret = -EFAULT;goto out;}memmove(dev->mem, dev->mem + count, dev->current_len - count);dev->current_len -= count;wake_up_interruptible(&dev->write_wait);ret = count;out:mutex_unlock(&dev->mutex);
out2:remove_wait_queue(&dev->read_wait, &wait);set_current_state(TASK_RUNNING);return ret;
}
5.4 写函数实现
static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{struct globalfifo_dev *dev = filp->private_data;DECLARE_WAITQUEUE(wait, current);int ret = 0;mutex_lock(&dev->mutex);add_wait_queue(&dev->write_wait, &wait);while (dev->current_len == FIFO_SIZE) {if (filp->f_flags & O_NONBLOCK) {ret = -EAGAIN;goto out;}__set_current_state(TASK_INTERRUPTIBLE);mutex_unlock(&dev->mutex);schedule();if (signal_pending(current)) {ret = -ERESTARTSYS;goto out2;}mutex_lock(&dev->mutex);}if (count > FIFO_SIZE - dev->current_len)count = FIFO_SIZE - dev->current_len;if (copy_from_user(dev->mem + dev->current_len, buf, count)) {ret = -EFAULT;goto out;}dev->current_len += count;wake_up_interruptible(&dev->read_wait);ret = count;out:mutex_unlock(&dev->mutex);
out2:remove_wait_queue(&dev->write_wait, &wait);set_current_state(TASK_RUNNING);return ret;
}
5.5 poll函数实现
static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)
{struct globalfifo_dev *dev = filp->private_data;unsigned int mask = 0;mutex_lock(&dev->mutex);poll_wait(filp, &dev->read_wait, wait);poll_wait(filp, &dev->write_wait, wait);if (dev->current_len != 0)mask |= POLLIN | POLLRDNORM;if (dev->current_len != FIFO_SIZE)mask |= POLLOUT | POLLWRNORM;mutex_unlock(&dev->mutex);return mask;
}
5.6 测试方法
- 加载驱动模块:
insmod globalfifo.ko
- 创建设备节点:
mknod /dev/globalfifo c 250 0
- 测试阻塞读:
# 终端1
cat /dev/globalfifo# 终端2
echo "Hello World" > /dev/globalfifo
- 测试非阻塞读:
cat /dev/globalfifo &
# 应该立即返回,显示资源暂时不可用
6. 非阻塞I/O实验:按键驱动实现
6.1 实验目标
实现一个支持非阻塞读的按键驱动:
- 当没有按键事件时,非阻塞读立即返回
- 当有按键事件时,读取按键值
- 支持中断处理
6.2 关键数据结构
struct key_dev {int gpio;int irq;char name[10];atomic_t key_value;atomic_t key_pressed;wait_queue_head_t waitq;
};
6.3 读函数实现
static ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{struct key_dev *dev = filp->private_data;int ret;unsigned char value;if (filp->f_flags & O_NONBLOCK) {if (!atomic_read(&dev->key_pressed))return -EAGAIN;} else {wait_event_interruptible(dev->waitq, atomic_read(&dev->key_pressed));}value = atomic_read(&dev->key_value);if (copy_to_user(buf, &value, 1))return -EFAULT;atomic_set(&dev->key_pressed, 0);return 1;
}
6.4 中断处理函数
static irqreturn_t key_irq_handler(int irq, void *dev_id)
{struct key_dev *dev = dev_id;int gpio_value = gpio_get_value(dev->gpio);if (gpio_value == 0) { // 按键按下atomic_set(&dev->key_value, KEY_VALUE_PRESSED);} else { // 按键释放atomic_set(&dev->key_value, KEY_VALUE_RELEASED);atomic_set(&dev->key_pressed, 1);wake_up_interruptible(&dev->waitq);}return IRQ_HANDLED;
}
6.5 测试方法
- 加载驱动模块:
insmod key.ko
- 创建设备节点:
mknod /dev/key c 240 0
- 测试非阻塞读:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main()
{int fd = open("/dev/key", O_RDONLY | O_NONBLOCK);char key_val;while (1) {if (read(fd, &key_val, 1) == 1) {printf("Key event: %d\n", key_val);} else {printf("No key event, doing other work...\n");sleep(1);}}close(fd);return 0;
}
7. 总结与选择建议
7.1 阻塞与非阻塞I/O对比
特性 | 阻塞I/O | 非阻塞I/O |
---|---|---|
行为 | 等待直到操作完成 | 立即返回,成功或失败 |
CPU使用 | 等待时不占用CPU | 需要主动轮询 |
响应性 | 低 | 高 |
编程复杂度 | 简单 | 较复杂 |
适用场景 | 简单同步操作 | 高并发或快速响应 |
7.2 选择建议
-
选择阻塞I/O当:
- 处理简单的顺序任务
- 不需要同时处理多个I/O操作
- 资源通常能快速就绪
-
选择非阻塞I/O当:
- 需要同时监控多个I/O操作
- 要求快速响应
- 处理高并发连接
-
对于驱动开发者:
- 通常需要同时支持阻塞和非阻塞模式
- 正确实现等待队列和poll操作
- 注意并发控制和竞态条件
通过理解阻塞和非阻塞I/O的原理和实现方式,开发者可以根据具体应用场景选择最合适的I/O模型,编写出高效可靠的Linux驱动程序。
相关文章:
Linux阻塞与非阻塞I/O:从原理到实践详解
Linux阻塞与非阻塞I/O:从原理到实践详解 1. 阻塞与非阻塞I/O基础概念 1.1 阻塞与非阻塞简介 在Linux系统编程中,I/O操作可以分为两种基本模式:阻塞I/O和非阻塞I/O。这两种模式决定了当设备或资源不可用时,程序的行为方式。 阻…...
form表单提交前设置请求头request header及文件下载
需求:想要在form表单submit之前,设置一下请求头。 除了用Ajax发起请求之外,还可以使用FormData来实现,咱不懂就问。 1 问:FormData什么时间出现的?与ajax什么联系? 2 问:FormData使…...
整合 CountVectorizer 和 TfidfVectorizer 绘制词云图
本文分别整合 CountVectorizer 和 TfidfVectorizer 绘制词云图 ✨ CountVectorizer CountVectorizer 是 scikit-learn 中用于 文本特征提取 的一个工具,它的主要作用是将一组文本(文本集合)转换为词频向量(Bag-of-Words…...
国产AI大模型超深度横评:技术参数全解、商业落地全场景拆解
评测方法论与指标体系 评测框架设计 采用三层评估体系,涵盖技术性能、商业价值、社会效益三大维度,细分为12个二级指标、36个三级指标: 测试环境配置 项目配置详情硬件平台8NVIDIA H100集群,NVLink全互联,3TB内存软…...
Shell脚本-流程控制语句应用案例
在Shell脚本编程中,流程控制语句是实现逻辑控制和自动化任务处理的关键。通过合理运用条件判断、循环等流程控制语句,可以编写出高效、灵活的脚本程序。本文将通过几个实际的应用案例来展示如何使用这些流程控制语句解决具体的编程问题。 案例一&#x…...
HarmonyOS NEXT应用开发-Notification Kit(用户通知服务)notificationManager.addSlot
1.notificationManager.addSlot 支持设备Phone2in1TabletCarWearable addSlot(type: SlotType, callback: AsyncCallback<void>): void 创建指定类型的通知渠道。使用callback异步回调。 系统能力:SystemCapability.Notification.Notification 示例…...
计算机网络核心知识点全解析(面试通关版)
一、网络体系结构:从OSI到TCP/IP的分层设计 1.1 七层模型与四层模型对比 OSI七层模型核心功能TCP/IP四层对应典型协议生活类比应用层为应用程序提供服务(如文件传输、邮件、Web浏览)应用层HTTP、FTP、SMTP、DNS快递面单信息(收件…...
表示学习与部分域适应
表示学习(Representation Learning) 表示学习是机器学习的一个分支,旨在自动从原始数据中提取有意义的特征或表示,使得这些表示更适合后续任务(如分类、检测、回归等)。其核心思想是将高维、复杂、冗余的原…...
AI与思维模型【77】——PDCA思维模型
一、定义 PDCA思维模型是一种用于持续改进和优化工作流程、项目实施以及问题解决的科学管理方法。它由四个英文字母组成,分别代表计划(Plan)、执行(Do)、检查(Check)和处理(Act&…...
Flink 系列之七 - Data Stream API的源算子原理
之前做过数据平台,对于实时数据采集,使用了Flink。现在想想,在数据开发平台中,Flink的身影几乎无处不在,由于之前是边用边学,总体有点混乱,借此空隙,整理一下Flink的内容,…...
使用 SSE + WebFlux 推送日志信息到前端
为什么使用 SSE 而不使用 WebSocket, 请看 SEE 对比 Websocket 的优缺点。 特性SSEWebSocket通信方向单向(服务器→客户端)双向(全双工)协议基于 HTTP独立协议(需 ws:// 前缀)兼容性现代浏览器(…...
Java多线程同步有哪些方法?
大家好,我是锋哥。今天分享关于【Java多线程同步有哪些方法?】面试题。希望对大家有帮助; Java多线程同步有哪些方法? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中,多线程同步是确保多个线程在访问共享资源时不会…...
Java—数 组
数组就是一个容器,用来存一批同种类型的数据。 一、静态初始化数组 1.1 定义方式 语法: 完整格式:数据类型 [ ] 数组名 new 数据类型 []{ 元素 1 ,元素 2 ,元素3… };简化格式:数据类型 [ ] 数组名 {…...
iOS/Android 使用 C++ 跨平台模块时的内存与生命周期管理
在移动应用开发领域,跨平台开发已经成为一种不可忽视的趋势。随着智能手机市场的持续扩张,开发者需要同时满足iOS和Android两大主流平台的需求,而这往往意味着重复的工作量和高昂的维护成本。跨平台开发的目标在于通过一套代码库实现多平台的支持,从而降低开发成本、加速产…...
为什么vue的key值,不用index?
在 Vue 中,key 的作用是帮助框架高效地识别和复用 DOM 节点或组件实例。使用数组索引 (index) 作为 key 值可能会导致以下问题,因此通常不建议这样做: 1. 列表数据变化时,可能导致错误的 DOM 复用 问题:当列表的顺序…...
Hi3516CV608 超高清智慧视觉 SoC 芯片 可提供开发资料
Hi3516CV608 超高清智慧视觉SoC 产品简介 总体介绍 Hi3516CV608是一颗面向消费类市场的IPC SoC,在新一代视频编解码标准、网络安全、隐私保护和人工智能方面引领行业发展。主要应用于室内外场景下的云台机、枪机、球机、枪球一体机、双目长短焦机等产品形态&#…...
Flink部署与应用——部署方式介绍
引入 我们通过Flink相关论文的介绍,对于Flink已经有了初步理解,这里简单的梳理一下Flink常见的部署方式。 Flink 的部署方式 StandAlone模式 介绍 StandAlone模式是Flink框架自带的分布式部署模式,不依赖其他的资源调度框架,…...
数据挖掘技术与应用课程论文——数据挖掘中的聚类分析方法及其应用研究
数据挖掘中的聚类分析方法及其应用研究 摘要 聚类分析是数据挖掘技术中的一个重要组成部分,它通过将数据集中的对象划分为多个组或簇,使得同一簇内的对象具有较高的相似性,而不同簇之间的对象具有较低的相似性。 本文系统地研究了数据挖掘中的多种聚类分析方法及其应用。首先…...
SIEMENS PLC程序解读 ST 语言 车型识别
1、ST程序代码 IF #Type1_MIX < #CFG_Type.Type.CT AND #CFG_Type.Type.CT < #Type1_MAX AND #CFG_Type.Type.CT<>0 THEN#Type[1] : 1;FOR #I : 0 TO 39 DOIF #CFG_Type.Type.CT/10 (#Type1_MIX 10 * #I)/10 THEN#Sub_Type."1"[#I 1] : 1;END_IF; E…...
神经网络基础[损失函数,bp算法,梯度下降算法 ]
关于神经网络的基础的概念可以看我前面的文章 损失函数 在深度学习中, 损失函数是用来衡量模型参数的质量的函数, 衡量的方式是比较网络输出和真实输出的差异 作用:指导模型的训练过程,通过反向传播算法计算梯度,从而更新网络的参数,最终使…...
python打印颜色(python颜色、python print颜色、python打印彩色文字、python print彩色、python彩色文字)
文章目录 python怎么打印彩色文字1. 使用ANSI转义码:2. 使用colorama库(更好的跨平台支持):3. 使用termcolor库: python怎么打印彩色文字 在Python中打印彩色文字有几种方法: 1. 使用ANSI转义码ÿ…...
数字域残留频偏的补偿原理
模拟域的频谱搬移一般通过混频器实现。一般情况下模拟域调整完频偏后数字域还会存在一部分残留频偏这部分就需要在数字域补偿。原理比较简单本文进行下粗略总结。首先我们需要了解下采样具体可参考下信号与系统笔记(六):采样 - 知乎。 采样前和采样后,角…...
Linux文件管理2
Linux 文件管理是系统操作的核心内容之一,涉及文件和目录的创建、删除、移动、查看、权限管理等操作。以下是 Linux 文件管理的核心知识点和常用操作总结: 一、文件系统结构 Linux 文件系统采用 树形结构,以 /(根目录࿰…...
C++----模拟实现string
模拟实现string,首先我们要知道成员变量有哪些: class _string{private:char* _str;size_t capacity;//空间有多大size_t size;//有效字符多少const static size_t npos;};const size_t _string::npos-1;//static在外面定义不需要带static,np…...
Python torch.optim.lr_scheduler 常用学习率调度器使用方法
在看学习率调度器之前,我们先看一下学习率的相关知识: 学习率 学习率的定义 学习率(Learning Rate)是深度学习中一个关键的超参数,它决定了在优化算法(如梯度下降法)更新模型参数时࿰…...
从零开始学Python游戏编程39-碰撞处理1
在《从零开始学Python游戏编程38-精灵5》代码的基础上,添加两个敌人的防御塔,玩家的坦克无法移动到防御塔所在的空格中,如图1所示。 图1 游戏中的碰撞处理 1 游戏中空格的坐标 在《从零开始学Python游戏编程36-精灵3》中提到,可…...
同步定时器的用户数要和线程组保持一致,否则jmeter会出现接口不执行’stop‘和‘×’的情况
调试压测时发现了一个问题就是线程计划总是出现‘stop’的按钮无法执行完毕 发现时同步定时器导致的,就是有接口使用了同步定时器,但是这个同步定时器的用户数量设置的<线程组用户数量时,会出现执行无法结束的情况,如下…...
如何在Linux用libevent写一个聊天服务器
废话少说,先看看思路 因为libevent的回调机制,我们可以借助这个机制来创建bufferevent来实现用户和用户进行通信 如果成功连接后我们可以直接在listener回调函数里创建一个bufferevent缓冲区,并为每个缓冲区设置相应的读回调和事件回调&…...
Virtuoso ADE采用Spectre仿真中出现MOS管最小长宽比满足要求依然报错的情况解决方法
在ADE仿真中错误问题如下: ERROR (CMI-2440): "xxx.scs" 46338: I2.M1: The length, width, or area of the instance does not fit the given lmax-lmin, wmax-wmin, or areamax-areamin range for any model in the I2.M3.nch_hvt group. The channel w…...
防火墙原理与应用总结
防火墙介绍: 防火墙(Firewall)是一种网络安全设备,其核心目标是通过分析数据包的源地址、端口、协议等内容,保护一个网络区域免受来自另一个网络区域的网络攻击和网络入侵行为,同时允许合法流量自由通行。…...
Graph Database Self-Managed Neo4j 知识图谱存储实践2:通过官方新手例子入门(未完成)
官方入门例子:neo4j-graph-examples/get-started: An introduction to graph databases and Neo4j for new users 官方例子仓库:https://github.com/neo4j-graph-examples 下载数据 git clone https://github.com/neo4j-graph-examples/get-started …...
GIT下载步骤
git官方链接: 添加链接描述...
C++中的vector和list的区别与适用场景
区别 特性vectorlist底层实现动态数组双向链表内存分配连续内存块非连续内存块随机访问支持,通过索引访问,时间复杂度O(1)不支持,需遍历,时间复杂度O(n)插入/删除末尾操作效率高,时间复杂度O(1)任意位置操作效率高&am…...
软件测试入门学习笔记
今天学习新知识,软件测试。 什么是软件测试? 使用人工和自动手段来运行或测试某个系统的过程,目的在于检验它是否满足规定的需求或弄清实际结果与预期结果之间的差别。 软件测试的目的? 1)为了发现程序࿰…...
2025年深度学习模型发展全景透视(基于前沿技术突破与开源生态演进的交叉分析)
2025年深度学习模型发展全景透视 (基于前沿技术突破与开源生态演进的交叉分析) 一、技术突破与能力边界拓展 智能水平跃升 2025年开源模型如Meta Llama-4、阿里Qwen2.5-VL参数规模突破1300亿,在常识推理能力测试中首次超越人类基准线7.2%谷歌…...
时间复杂度分析
复杂度分析的必要性: 当给我们一段代码时,我们是以什么准则来判断代码效率的高低呢?每一段代码都会消耗一段时间,或占据一段数据空间,那么自然是在实现相同功能的情况下,代码所耗时间最少,所占…...
BGE-m3 和 BCE-Embedding 模型对比分析
以下是对 BGE-m3 和 BCE-Embedding 模型在 embedding 领域的多维度对比分析,基于公开的技术文档和实验数据: 1. 基础信息对比 维度BGE-m3 (智源研究院)BCE-Embedding (网易)发布时间2024 年 1 月2023 年 9 月模型架构Transformer-basedTransformer-base…...
题目 3320: 蓝桥杯2025年第十六届省赛真题-产值调整
题目 3320: 蓝桥杯2025年第十六届省赛真题-产值调整 时间限制: 2s 内存限制: 192MB 提交: 549 解决: 122 题目描述 偏远的小镇上,三兄弟共同经营着一家小型矿业公司 “兄弟矿业”。公司旗下有三座矿山:金矿、银矿和铜矿,它们的初始产值分别用…...
计算机组成原理第二章 数据的表示和运算——2.1数制与编码
计算机组成原理第二章 数据的表示和运算——数制与编码 一、基本概念与核心知识点 1.1 数制系统基础 1.1.1 进位计数制 定义:以固定基数(如2、8、10、16)表示数值的系统核心要素: 基数(R):允…...
基于归纳共形预测的大型视觉-语言模型中预测集的**数据驱动校准**
摘要 本研究通过分离共形预测(SCP)框架,解决了大型视觉语言模型(LVLMs)在视觉问答(VQA)任务中幻觉缓解的关键挑战。虽然LVLMs在多模态推理方面表现出色,但它们的输出常常表现出具有…...
Golang | 自行实现并发安全的Map
核心思路,读写map之前加锁!哈希思路,大map化分为很多个小map...
【Python数据库编程实战】从SQL到ORM的完整指南
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1:SQLite基础操作案例2:MySQL连接池案例3:SQLAlchemy ORM …...
深入剖析扣子智能体的工作流与实战案例
前面我们已经初步带大家体验过扣子工作流,工作流程是 Coze 最为强大的功能之一,它如同扣子中蕴含的奇妙魔法工具,赋予我们的机器人处理极其复杂问题逻辑的能力。 这篇文章会带你更加深入地去理解并运用工作流解决实际问题 目录 一、工作流…...
【计算机网络】IP地址
IPv4 五类地址 1.0.0.0 ~ 126.255.255.255A类子网8位,主机24位128.0.0.0 ~ 191.255.255.255B类子网16位,主机16位192.0.0.0 ~ 223.255.255.255C类子网24位,主机8位224.0.0.0 ~ 239.255.255.255D类不分网络地址和主机地址,作为组播…...
基于CATIA参数化管道建模的自动化插件开发实践——NX建模之管道命令的参考与移植
引言 在机械设计领域,CATIA作为行业领先的CAD软件,其强大的参数化建模能力备受青睐。本文介绍如何利用Python的PySide6框架与CATIA二次开发技术,开发一款智能管状体生成工具。该工具借鉴了同类工业软件NX的建模的管道命令,通过Py…...
运维之SSD硬盘(SSD hard Drive for Operation and Maintenance)
背景 SSD的产生背景是计算技术发展和市场需求驱动的结果。早期计算机使用磁芯存储器,后来被半导体存储器取代,提高了速度和可靠性。随着电子设备小型化,对轻便、低功耗存储器的需求增长,SSD因无机械部件、速度快、耗电少而受到关…...
基于javaweb的SSM+Maven红酒朔源管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
HTML 地理定位(Geolocation)教程
HTML 地理定位(Geolocation)教程 简介 HTML5 的 Geolocation API 允许网页应用获取用户的地理位置信息。这个功能可用于提供基于位置的服务,如导航、本地搜索、天气预报等。本教程将详细介绍如何在网页中实现地理定位功能。 工作原理 浏览器可以通过多种方式确定…...
RHEL与CentOS:从同源到分流的开源操作系统演进
RHEL与CentOS:从同源到分流的开源操作系统演进 一、核心关系:源代码的重构与社区化 RHEL(Red Hat Enterprise Linux)与CentOS(Community ENTerprise Operating System)的关系可以概括为“同源异构”。RHE…...
架构师面试(三十六):广播消息
题目 在像 IM、短视频、游戏等实时在线类的业务系统中,一般会有【广播消息】业务,这类业务具有瞬时高流量的特点。 在对【广播消息】业务实现时通常需要同时写 “系统消息库” 和更新用户的 “联系人库” 的操作,用户的联系人表中会有未读数…...