zoukankan      html  css  js  c++  java
  • Linux网络编程--sendfile零拷贝高效率发送文件

    from http://blog.csdn.net/hnlyyk/article/details/50856268

    Linux系统使用man sendfile,查看sendfile原型如下:

    #include <sys/sendfile.h>

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

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

    out_fd必须是一个socket描述符。

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

    Sendfile 函数在两个文件描述符之间直接传递数据(完全在内核中操作,传送),从而避免了内核缓冲区数据和用户缓冲区数据之间的拷贝,操作效率很高,被称之为零拷贝。

    传统方式read/write send/recv 
    在传统的文件传输里面(read/write方式),在实现上其实是比较复杂的,需要经过多次上下文的切换,我们看一下如下两行代码:    
    1. read(file, tmp_buf, len);        

    2. write(socket, tmp_buf, len);   

    以上两行代码是传统的read/write方式进行文件到socket的传输。    

    当需要对一个文件进行传输的时候,其具体流程细节如下:   

    1、调用read函数,文件数据被copy到内核缓冲区  

    2、read函数返回,文件数据从内核缓冲区copy到用户缓冲区 

    3、write函数调用,将文件数据从用户缓冲区copy到内核与socket相关的缓冲区。

     4、数据从socket缓冲区copy到相关协议引擎。    

    以上细节是传统read/write方式进行网络文件传输的方式,我们可以看到,

    在这个过程当中,文件数据实际上是经过了四次copy操作:    硬盘—>内核buf—>用户buf—>socket相关缓冲区(内核)—>协议引擎

     

    新方式sendfile  

    sendfile系统调用则提供了一种减少以上多次copy,提升文件传输性能的方法。

    1、系统调用 sendfile() 通过 DMA 把硬盘数据拷贝到 kernel buffer,然后数据被 kernel 直接拷贝到另外一个与 socket 相关的 kernel buffer。这里没有 user mode 和 kernel mode 之间的切换,在 kernel 中直接完成了从一个 buffer 到另一个 buffer 的拷贝。
    2、DMA 把数据从 kernel buffer 直接拷贝给协议栈,没有切换,也不需要数据从 user mode 拷贝到 kernel mode,因为数据就在 kernel 里。

  • 相关阅读:
    Windows Phone 7 ManipulationStarted 事件
    用C#实现AES加密和解密
    Windows Phone 7 程序菜单栏ApplicationBar
    Windows Phone 7 使用选择器(Chooser)
    Windows Phone 7 矢量图形编程
    Windows Phone 7 位图BitmapImage和WriteableBitmap
    Windows Phone 7 利用计时器DispatcherTimer创建时钟
    Windows Phone 7 配置文件WMAppmanifest.xml的介绍
    C#转换人民币大小金额
    Windows Phone 7 入门XAML语法介绍
  • 原文地址:https://www.cnblogs.com/kex1n/p/7446142.html
Copyright © 2011-2022 走看看