网络编程--零拷贝文件传输,网络编程范式
零拷贝1.为什么要有 DMA 技术?在没有 DMA 技术前I/O 的过程是这样的CPU 发出对应磁盘控制器收到指令后于是就开始准备数据会把数据放入到磁盘控制器的内部缓冲区中然后产生一个中断CPU 收到中断信号后停下手头的工作利用中断处理函数完成接着把磁盘控制器的缓冲区的数据一次一个字节地读进自己的寄存器然后再把寄存器里的数据写入到内存。什么是 DMA 技术在进行 I/O 设备和内存的数据传输的时候数据搬运的工作全部交给 DMA 控制器。早期 DMA 只存在在主板上如今由于 I/O 设备越来越多数据传输的需求也不尽相同所以每个 I/O 设备里面都有自己的 DMA 控制器。传统的文件传输有多糟糕代码通常如下一般会需要两个系统调用代码很简单虽然就两行代码但是这里面发生了不少的事情。期间共发生了 4 次用户态与内核态的上下文切换一个系统调用涉及用户态-内核态内核态-用户态算两次。上下文切换到成本并不小一次切换需要耗时几十纳秒到几微秒虽然时间看上去很短但是在高并发的场景下这类时间容易被累积和放大从而影响系统的性能。发生了 4 次数据拷贝第一次拷贝把磁盘上的数据拷贝到操作系统内核的缓冲区里这个拷贝的过程是通过 DMA 搬运的。第二次拷贝把内核缓冲区的数据拷贝到用户的缓冲区里这个拷贝到过程是由 CPU 完成的。第三次拷贝把刚才拷贝到用户的缓冲区里的数据再拷贝到内核的 socket 的缓冲区里这个过程依然还是由 CPU 搬运的。第四次拷贝把内核的 socket 缓冲区里的数据拷贝到网卡的缓冲区里这个过程又是由 DMA 搬运的。要想提高网络文件传输的性能就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数。如何实现零拷贝零拷贝技术实现的方式通常有 2 种mmap writesendfilemmap writemmap() 系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间这样操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。减少了一次数据拷贝。sendfile在 Linux 内核版本 2.1 中提供了一个专门发送文件的系统调用函数 sendfile()函数形式如下减少了一次系统调用和一次数据拷贝。如果网卡支持 SG-DMAThe Scatter-Gather Direct Memory Access技术和普通的 DMA 有所不同我们可以进一步减少通过 CPU 把内核缓冲区里的数据拷贝到 socket 缓冲区的过程。从 Linux 内核 2.4 版本开始起对于支持网卡支持 SG-DMA 技术的情况下 sendfile() 系统调用的过程发生了点变化具体过程如下第一步通过 DMA 将磁盘上的数据拷贝到内核缓冲区里第二步缓冲区描述符和数据长度传到 socket 缓冲区这样网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里。减少了一次系统调用两次数据拷贝。大文件传输用什么方式实现先来看看最初的例子当调用 read 方法读取文件时进程实际上会阻塞在 read 方法调用因为要等待磁盘数据的返回如下图对于阻塞的问题可以用异步 I/O 来解决它工作方式如下图通常对于磁盘异步 I/O 只支持直接 I/O。此时异步 I/O 并没有涉及到 PageCache。直接 I/O 应用场景常见的两种应用程序已经实现了磁盘数据的缓存那么可以不需要 PageCache 再次缓存减少额外的性能损耗。在 MySQL 数据库中可以通过参数设置开启直接 I/O默认是不开启由于直接 I/O 绕过了 PageCache就无法享受内核的这两点的优化内核的 I/O 调度算法会缓存尽可能多的 I/O 请求在 PageCache 中最后「合并」成一个更大的 I/O 请求再发给磁盘这样做是为了减少磁盘的寻址操作内核也会「预读」后续的 I/O 请求放在 PageCache 中一样是为了减少对磁盘的操作网络编程1.select将已连接的 Socket 都放到一个文件描述符集合然后调用 select 函数将文件描述符集合拷贝到内核里让内核来检查是否有网络事件产生。检查的方式很粗暴就是通过遍历文件描述符集合的方式当检查到有事件产生后将此 Socket 标记为可读或可写。接着再把整个文件描述符集合拷贝回用户态里。用户态还需要再通过遍历的方法找到可读或可写的 Socket然后再对其处理。需要 2 次「遍历」文件描述符集合2 次「拷贝」文件描述符集合。select 使用固定长度的 BitsMap表示文件描述符集合而且所支持的文件描述符的个数是有限制的在 Linux 系统中由内核中的 FD_SETSIZE 限制 默认最大值为 1024只能监听 0~1023 的文件描述符。2.poll过程类型。需要 2 次「遍历」文件描述符集合2 次「拷贝」文件描述符集合。poll 不再用 BitsMap 来存储所关注的文件描述符取而代之用动态数组以链表形式来组织突破了 select 的文件描述符个数限制当然还会受到系统文件描述符限制。3.epollepoll 通过两个方面很好解决了 select/poll 的问题。第一点epoll 在内核里使用红黑树来跟踪进程所有待检测的文件描述字把需要监控的 socket 通过 epoll_ctl() 函数加入内核中的红黑树里。这样避免了select/poll每次执行检测需要全量拷贝问题。第二点 epoll 使用事件驱动的机制内核里维护了一个链表来记录就绪事件当某个 socket 有事件发生时通过回调函数内核会将其加入到这个就绪事件列表中当用户调用 epoll_wait() 函数时只会返回有事件发生的文件描述符的个数。避免了select/poll每次检测需要全量扫描问题。边缘触发和水平触发epoll 支持两种事件触发模式分别是边缘触发edge-triggeredET和水平触发level-triggeredLT。这两个术语还挺抽象的其实它们的区别还是很好理解的。使用边缘触发模式时当被监控的 Socket 描述符上有可读事件发生时服务器端只会从 epoll_wait 中苏醒一次。使用水平触发模式时当被监控的 Socket 上有可读事件发生时服务器端不断地从 epoll_wait 中苏醒直到内核缓冲区数据被 read 函数读完才结束。

相关新闻

如何快速搭建智能媒体库:MetaTube插件为Jellyfin/Emby打造的终极元数据管理方案

如何快速搭建智能媒体库:MetaTube插件为Jellyfin/Emby打造的终极元数据管理方案

如何快速搭建智能媒体库:MetaTube插件为Jellyfin/Emby打造的终极元数据管理方案 【免费下载链接】jellyfin-plugin-metatube MetaTube Plugin for Jellyfin/Emby 项目地址: https://gitcode.com/gh_mirrors/je/jellyfin-plugin-metatube 在当今数字媒体时代&…

2026/10/26 17:17:49 阅读更多 →
联合查询SQL注入攻击原理与防御实战

联合查询SQL注入攻击原理与防御实战

1. 联合查询注入的本质与攻击逻辑联合查询注入(Union-Based SQL Injection)是SQL注入攻击中最经典且高效的技术手段之一。这种攻击方式的核心在于利用SQL语句中的UNION操作符,将恶意构造的查询语句拼接到原始查询中,从而获取数据库…

2026/10/26 17:20:08 阅读更多 →
C++与C#中using、命名空间与作用域解析符的深度对比与实践指南

C++与C#中using、命名空间与作用域解析符的深度对比与实践指南

1. 项目概述:当C老炮遇上C#新贵 在跨语言开发或者技术栈迁移的日常里,我经常遇到一个有趣的现象:很多从C转向C#的朋友,或者反过来,都会对 using 这个关键字产生一种“似曾相识却又处处不同”的困惑。在C里&#xff0…

2026/10/26 17:26:51 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/28 7:28:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/28 9:02:11 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/28 9:00:54 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/28 7:29:02 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/28 9:01:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/27 19:19:37 阅读更多 →