码迷,mamicode.com
首页 > 其他好文 > 详细

零拷贝传输(zero-copy transfer)——sendfile()

时间:2015-06-12 23:47:33      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

  做Web服务器时通常需要将文件传送出去,其中一种方法是通过定义一个buffer每次读取文件发送给接收端。大多数服务器会选择sendfile的方式,nginx实现时就是采用这种方式。对于并发搞得服务器性能上能得到优势。

  技术分享

  对于第一种方式需要进入内核两次,分别是读取磁盘文件和写入socket,对于操作系统而言进入内核的开销是不可以忽略的,而sendfile() 采取了所谓的 “zero-copy transfer” 的方式,数据在内核中的时候,就从cbuffer cache 送入 socket buffer中了。花销仅仅一次system call。为了突出显示这两者的区别,我选择发送一个大文件来体现他们之间的效率的差距:

send() 关键代码:

(发送文件时定义了一个协议:每次读取文件先将大小发送过去,告诉接收端,这次要接受多大的内容)

1 for(;;)
2 {
3     bzero(buf,sizeof(buf));
4     size = read(file_fd,buf,sizeof(buf));
5     if(!size)
6         break;
7     send(fd,&size,sizeof(size),0);
8     send(fd,buf,size,0);
9 }

sendfile() 关键代码 :

sendfile(fd,file,&n,len);

 

结果比较:

1.

$time a.out
file
All done!

real 0m4.667s
user 0m0.148s
sys 0m1.744s

2.

$time a.out
file
All done.

real 0m3.113s
user 0m0.000s
sys 0m0.020s

 

  仅仅50M的文件就相差1s了,可以看出主要的差距还是内核时间。服务器选择发送文件时还是sendfile比较靠谱一点。

最后sendfile的原型:

  ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

  其中in_fd必须是可以进行mmap()操作的,这也就是说接收端不可以用sendfile()接受的,即使前两个参数都是fd,容易给人这样的错觉。

零拷贝传输(zero-copy transfer)——sendfile()

标签:

原文地址:http://www.cnblogs.com/ittinybird/p/4572799.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!