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

sendfile学习

时间:2017-01-22 23:34:14      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:方式   成本   --   images   size   linux   off   可见   不能   

参考

https://zhuanlan.zhihu.com/p/20768200?refer=auxten

 

而成本很多时候的体现就是对计算资源的消耗,其中最重要的一个资源就是CPU资源。

 

Sendfile(2)在这个时代背景下于2003年前后被加入Linux Kernel,陆续在各大UNIX、Linux、Solaris平台上获得了支持。这个系统内核调用本身被设计出来是用来从磁盘到TCP协议栈拷贝数据用的,但也我们也是可以把它用来做两个文件之间的数据拷贝。

在Linux Kernel 2.6版本中,这个系统调用的原型是这样的:

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
  • in_fd 被打开是等待读数据的fd.
  • out_fd 被打开是等待写数据的fd.
  • Offset 是在正式开始读取数据之前应该向前偏移的byte数.
  • count 是需要在两个fd之间“搬移”的数据的byte数.

参数特别注意的是:in_fd必须是一个支持mmap函数的文件描述符,也就是说必须指向真实文件,不能使socket描述符和管道。

out_fd必须是一个socket描述符。

由此可见sendfile几乎是专门为在网络上传输文件而设计的。


在sendfile(2)出现之前,我们想要把一个文件发送到socket上需要进行如下几个步骤:

  1. 调用read(2)函数,文件数据被copy到内核缓冲区
  2. read(2)函数返回,文件数据从内核缓冲区copy到用户缓冲区
  3. write(2)函数调用,将文件数据从用户缓冲区copy到内核与socket相关的缓冲区。
  4. 数据从socket缓冲区copy到相关协议引擎。
技术分享

 

 

相比sendfile(2),“Read & Write”方式带来的性能损耗主要有两点:

  1. 不必要的内存拷贝。
  2. 系统调用带来的额外的用户态/内核态上下文切换(Context Switch)。

技术分享

 

 

而我们知道,上下文切换涉及到非常多的CPU、内存堆栈的操作,会让分支预测失败率大增,所以频繁的上线文切换是高性能编程的大忌。类UNIX操作系统里都有一个系统命令vmstat可以展示当前系统的“Context Switch”的量(--system--下的cs列):

技术分享

 

 

sendfile学习

标签:方式   成本   --   images   size   linux   off   可见   不能   

原文地址:http://www.cnblogs.com/charlesblc/p/6341605.html

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