zoukankan      html  css  js  c++  java
  • 零拷贝传输(zero-copy transfer)——sendfile()

      做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,容易给人这样的错觉。

  • 相关阅读:
    常用的输出方法
    使用Action()和ActionLink()生成链接
    "??"运算符
    使用路由数据
    路由匹配总结
    routes.MapRoute()定义路由的要求
    控制器和视图数据传递小结
    跨请求数据传递TempData
    Redis安装创建
    JAVA获取当前时间加一天
  • 原文地址:https://www.cnblogs.com/ittinybird/p/4572799.html
Copyright © 2011-2022 走看看