[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f8w-YGqIXlmxxy-t8e22vl8sx1KqNivZvEJysTXvW-D8":3},{"item":4,"related":44},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":36,"sourceUrl":37,"status":38,"seoTitle":7,"seoDescription":9,"canonicalUrl":35,"isFeatured":39,"sno":40,"sortOrder":41,"publishedAt":42,"updatedAt":43,"createdAt":43},"71c50502-fca9-48b4-b4b6-cbf03ac63707","article","Zero-copy：数据从磁盘到网卡，能不能不经过用户态拷贝？","zero-copy-io-explained","Zero-copy 通过减少用户态与内核态之间的数据搬运，降低大文件传输的 CPU 和内存带宽开销，但仍受硬件、加密与数据生命周期约束。","一次网络传输看起来很简单：从文件读出字节，再写入套接字。但如果数据只是从磁盘搬到网卡，先复制到用户态缓冲区，再复制回内核态，就会产生不必要的 CPU 和内存带宽消耗。Zero-copy（零拷贝）关注的正是如何减少这些中间搬运。\n\n以 Linux 的 sendfile 为例，应用只需告诉内核“把这个文件描述符的内容发送到那个套接字”。内核可以在自己的缓存和网络发送路径之间转移数据，应用不必把每个字节读进自己的缓冲区。对静态文件服务器、代理和大文件分发来说，这能减少用户态与内核态之间的往返。\n\n这里的“零”是工程语境里的零：通常意味着少一次或几次 CPU 参与的数据复制，并不保证物理内存里完全没有任何复制。网卡 DMA、文件系统缓存、加密、压缩、协议封装和硬件能力，都会决定最终路径。某些场景仍需复制，例如数据要被修改、格式转换，或协议栈无法直接引用原始页面。\n\n零拷贝还带来生命周期约束。发送操作尚未完成时，源文件内容不能被随意改写或截断，否则内核可能看到不一致的数据。应用需要处理部分发送、阻塞、错误和背压，不能因为接口看起来是一条直通管道就忽略流量控制。\n\n它的价值不在于追求一个漂亮的术语，而在于把 CPU 从“搬运工”角色中释放出来。是否值得使用，要看数据大小、传输频率、硬件和系统调用路径；小数据、复杂变换或强加密场景未必适合。先画清楚数据从哪里到哪里，再决定删除哪一次复制，通常比盲目追求零拷贝更可靠。\n\n另外，零拷贝并不意味着应用可以忘记背压。发送端必须知道内核何时真正消费了源页面，接收端慢时仍要限制在途数据；否则只是把内存占用从用户态缓冲区转移到内核队列。性能测试也应同时记录 CPU、内存带宽、吞吐和尾延迟，避免只凭系统调用次数得出结论。\n\n资料来源：[Linux sendfile(2) 手册](https:\u002F\u002Fwww.man7.org\u002Flinux\u002Fman-pages\u002Fman2\u002Fsendfile.2.html)","\u002Fuploads\u002F2026-09-26\u002F026281cd-4565-4311-9457-34d0b7fba9a7.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":32,"name":33,"slug":34},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",null,"Linux sendfile(2) 手册","https:\u002F\u002Fwww.man7.org\u002Flinux\u002Fman-pages\u002Fman2\u002Fsendfile.2.html?source=post_page---------------------------","published",false,49,0,"2026-09-27T00:00:00.000Z","2026-09-26T16:26:06.502Z",[45,54,62],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":52,"createdAt":53},"4ce57934-2b23-41a1-800e-bb2d8ab36684","Wasm Component Model：不同语言写的模块怎样用同一套接口协作？","wasm-component-model-wit-interfaces","WebAssembly Component Model 用有类型的接口描述组件如何交换数据与调用功能，WIT 则帮助表达这些接口。本文用模块化电器说明跨语言组合的意义，也指出它不代表程序脱离运行时就能在任何环境原样运行。","\u002Fuploads\u002F2026-10-17\u002F0eb1c88d-dc1f-486d-8194-54f72dd215ec.jpg",45,"2026-10-17T00:00:00.000Z","2026-10-17T03:08:52.474Z",{"id":55,"type":6,"title":56,"slug":57,"summary":58,"coverUrl":59,"authorName":14,"sno":51,"publishedAt":60,"createdAt":61},"07fe8e6e-82b0-46cc-9015-c6d027564430","pidfd：进程号会被重用，怎样才能稳定指向一个进程？","linux-pidfd-stable-process-reference","Linux pidfd 用文件描述符稳定引用一个进程，避免退出后的 PID 被重用而误操作新进程。本文介绍它的等待、信号用途和版本边界。","\u002Fuploads\u002F2026-10-06\u002F699e59f8-693f-47cb-87b1-c51764d1a679.jpg","2026-10-06T00:00:00.000Z","2026-10-06T07:51:27.054Z",{"id":63,"type":6,"title":64,"slug":65,"summary":66,"coverUrl":67,"authorName":14,"sno":51,"publishedAt":42,"createdAt":68},"15988123-6303-4ab1-ba01-dcc41f36329f","Futex：Linux 的锁为什么大多数时候根本不需要进内核？","futex-fast-userspace-locking","Futex 把无竞争时的锁操作留在用户态，只有真正需要睡眠和唤醒时才进入内核，是 Linux 高性能锁的关键低层构件。","\u002Fuploads\u002F2026-09-26\u002F90e98cc8-e57b-4dea-afc7-2afe7550d483.jpg","2026-09-26T16:25:54.119Z"]