分类:
2012-02-07 22:13:09
原文地址:使用 sendfile() 提升网络文件发送性能 作者:nbaloverme
偶见一好文,清楚地阐述了什么是零拷贝(Zero Copy)以及 sendfile 的由来,不复述下实感不快。
原文见:
文章中列出了我们平时通过网络发送文件时会用到的两个系统调用:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
在用户空间调用 read() 读取文件时发生两次内存拷贝:
接着调用 write() 把数据写入 socket 时,又发生了两次内存拷贝:
也就是说,在整个文件发送的过程中,发生了四次内存拷贝。
然后,数据读取到用户空间后并没有做过任何加工处理,因此通过网络发送文件时,根本没有必要把文件内容复制到用户空间。
于是引入了 mmap():
tmp_buf = mmap(file, len);
write(socket, tmp_buf, len);
这样一来,就少了用户空间和内核空间之间的内存复制了。
这种方式会有个问题,当前进程在调用 write() 时,另一个进程把文件清空了,程序就会报出 SIGBUS 类型错误。
Linux Kernel 2.1 引进了 sendfile(),只需要一个系统调用来实现文件发送。
sendfile(socket, file, len);
从性能上看,这种方式只是少了一个系统调用而已,还是做了3次拷贝操作。
Linux Kernel 2.4 改进了 sendfile(),调用接口没有变化:
sendfile(socket, file, len);
这样就只剩下2次拷贝啦。
在许多 http server 中,都引入了 sendfile 的机制,如 nginx、lighttpd 等,它们正是利用 sendfile() 这个特性来实现高性能的文件发送的。