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 里。

Linux网络编程--sendfile零拷贝高效率发送文件的更多相关文章

  1. Linux网络编程:UDP实现可靠的文件传输

    我们知道,用TCP实现文件传输很简单.相对于TCP,因为UDP是面向无连接.不可靠的传输协议,所以我们需要考虑丢包和后发先至(包的顺序)的问题,所以我们想要实现UDP传输文件,则需要解决这两个问题.方 ...

  2. linux网络编程九:splice函数,高效的零拷贝

    from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...

  3. Linux 网络编程(IO模型)

    针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...

  4. Linux网络编程(六)

    网络编程中,使用多路IO复用的典型场合: 1.当客户处理多个描述字时(交互式输入以及网络接口),必须使用IO复用. 2.一个客户同时处理多个套接口. 3.一个tcp服务程序既要处理监听套接口,又要处理 ...

  5. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

  6. 很全的linux网络编程技巧

    本文转载自:http://www.cnblogs.com/jfyl1573/p/6476607.html 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考 ...

  7. Linux网络编程简单示例

    linux 网络编程是通过socket(套接字)接口实现,Socket是一种文件描述符,socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开—读/写—关闭& ...

  8. Linux网络编程:UDP Socket编程范例

    TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...

  9. TCP/UDP Linux网络编程详解

    本文主要记录TCP/UDP网络编程的基础知识,采用TCP/UDP实现宿主机和目标机之间的网络通信. 内容目录 1. 目标2.Linux网络编程基础2.1 嵌套字2.2 端口2.3 网络地址2.3.1 ...

随机推荐

  1. Servlet笔记9--转发与重定向

    关于Web中资源跳转的问题: 转发和重定向基本代码: package com.bjpowernode.javaweb; import java.io.IOException; import javax ...

  2. /etc/sysctl.conf 调优 & 优化Linux内核参数

    from: http://apps.hi.baidu.com/share/detail/15652067 http://keyknight.blog.163.com/blog/static/36637 ...

  3. nginx在使用非80端口做反向代理【转】

    设置nginx反向代理,nginx在使用非80端口做反向代理时,浏览器访问发现返回302错误 upstream jboss{ server max_fails= fail_timeout=20s; s ...

  4. 使用SpringCloud搭建高可用服务注册中心

    我们需要的,不仅仅是一个服务注册中心而已,而是一个高可用服务注册中心. 上篇博客中我们介绍了如何使用Spring Cloud搭建一个服务注册中心,但是搭建好的服务注册中心是一个单节点的服务注册中心,这 ...

  5. C++ Primer读书笔记(2)

    getline(cin,string s)可以读取一整行,包括空白符.使用ctrl+Z结束 字符串字面值与string是不同的类型.两个字符串字面值不能直接相加. 处理string对象中的字符时,C+ ...

  6. java Stack(栈)

    "Stack" 通常时指"后进后出"(LIFO)的容器,有时栈也被称为叠加栈,因为最后"压入"栈的元素,第一个"弹出"栈 ...

  7. [转] map/reduce

    如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clusters”,你就能大概明白map/reduce的概念. ...

  8. ajax和jsonp

    ajax和jsonp 前言:ajax和jsonp可以与后台通信,获取数据和信息,但是又不用刷新整个页面,实现页面的局部刷新. 一.ajax 定义:一种发送http请求与后台进行异步通讯的技术. 原理: ...

  9. Codeforces Round #254 (Div. 1) D - DZY Loves Strings

    D - DZY Loves Strings 思路:感觉这种把询问按大小分成两类解决的问题都很不好想.. https://codeforces.com/blog/entry/12959 题解说得很清楚啦 ...

  10. Flume分布式日志收集系统

    1.flume是分布式的日志收集系统,把收集来的数据传送到目的地去.2.flume里面有个核心概念,叫做agent.agent是一个java进程,运行在日志收集节点.通过agent接收日志,然后暂存起 ...