使用 sendfile() 提升网络文件发送性能
来源:互联网 发布:mysql查询不重复数据 编辑:程序博客网 时间:2024/05/22 16:49
http://hily.me/blog/2011/01/use-sendfile-accelerate-file-sending/
偶见一好文,清楚地阐述了什么是零拷贝(Zero Copy)以及 sendfile 的由来,不复述下实感不快。
原文见:http://www.linuxjournal.com/article/6345
文章中列出了我们平时通过网络发送文件时会用到的两个系统调用:read(file, tmp_buf, len);
write(socket, tmp_buf, len);
调用过程示意图如下:
在用户空间调用 read() 读取文件时发生两次内存拷贝:
- DMA引擎将文件读取到内核的文件缓冲区
- 调用返回用户空间时将内核的文件缓冲区的数据复制到用户空间的缓冲区
接着调用 write() 把数据写入 socket 时,又发生了两次内存拷贝:
- 将用户空间的缓冲区的数据复制到内核的 socket 缓冲区
- 将内核 socket 缓冲区的数据复制到网络协议引擎
也就是说,在整个文件发送的过程中,发生了四次内存拷贝。
然后,数据读取到用户空间后并没有做过任何加工处理,因此通过网络发送文件时,根本没有必要把文件内容复制到用户空间。
于是引入了 mmap():tmp_buf = mmap(file, len);
write(socket, tmp_buf, len);
调用过程示意图:
- 调用 mmap() 时会将文件直接读取到内核缓冲区,并把内核缓冲区直接共享到用户空间
- 调用 write() 时,直接将内核缓冲区的数据复制到网络协议引擎
这样一来,就少了用户空间和内核空间之间的内存复制了。
这种方式会有个问题,当前进程在调用 write() 时,另一个进程把文件清空了,程序就会报出 SIGBUS 类型错误。
Linux Kernel 2.1 引进了 sendfile(),只需要一个系统调用来实现文件发送。sendfile(socket, file, len);
调用过程示意图:
- 调用 sendfile() 时会直接在内核空间把文件读取到内核的文件缓冲区
- 将内核的文件缓冲区的数据复制到内核的 socket 缓冲区中
- 将内核的 socket 缓冲区的数据复制到网络协议引擎
从性能上看,这种方式只是少了一个系统调用而已,还是做了3次拷贝操作。
Linux Kernel 2.4 改进了 sendfile(),调用接口没有变化:sendfile(socket, file, len);
调用过程示意图:
- 调用 sendfile() 时会直接在内核空间把文件读取到内核的文件缓冲区
- 内核的 socket 缓冲区中保存的是当前要发送的数据在内核的文件缓冲区中的位置和偏移量
- DMA gather copy 将内核的文件缓冲区的数据复制到网络协议引擎
这样就只剩下2次拷贝啦。
在许多 http server 中,都引入了 sendfile 的机制,如 nginx、lighttpd 等,它们正是利用 sendfile() 这个特性来实现高性能的文件发送的。
– EOF –
- 使用 sendfile() 提升网络文件发送性能
- 使用 sendfile() 提升网络文件发送性能
- 使用sendfile() 提高网络文件发送性能
- 使用sendfile提升性能
- Apache,Nginx,Lighttpd分别使用X-sendfile功能提升文件下载性能
- Apache,Nginx,Lighttpd分别使用X-sendfile功能提升文件下载性能
- 使用 Nginx 的 X-Sendfile 机制提升 PHP 文件下载性能
- 使用Nginx的X-Sendfile机制提升PHP文件下载性能
- Linux网络编程--sendfile零拷贝高效率发送文件
- Linux网络编程--sendfile零拷贝高效率发送文件
- Linux网络编程--sendfile零拷贝高效率发送文件
- Linux网络编程--sendfile零拷贝高效率发送文件
- sendfile原理,实现文件传输性能的提升
- sendfile()对Nginx性能的提升
- sendfile()对Nginx性能的提升
- sendfile()对Nginx性能的提升
- sendfile原理,实现文件传输性能的提升
- sendfile原理,实现文件传输性能的提升
- Android 内存使用hprof文件打开方法
- Webdriver - Selenium Grid Configuration
- 黑马程序员-预处理指令
- android文件读写,ndk文件读写
- 递归遍历某个路径下的文件
- 使用 sendfile() 提升网络文件发送性能
- 保存android程序崩溃日志到SD卡
- JPA 开发所需的Jar包 (基于Hibernate)
- 高效的JavaScript代码编写技巧
- 免费的云端软件测试平台-快意测试云平台介绍
- TCP协议三次握手过程分析
- Android 游戏检测碰撞方法:多种检测碰撞的定义及说明
- 常见gstreamer pipeline 命令
- 醒涨部琳刚释赏芬锤叛饰优逞廖糖