sendfile零拷贝

来源:互联网 发布:ubuntu 12.04 163源 编辑:程序博客网 时间:2024/05/17 21:52

sendfile函数

#include<sys/sendfile.h>ssize_t sendfile(int outfd,int in_fd,off_t* offset,size_t count);

in_fd是待读出内容的文件描述符,out_fd参数是待写入内容的文件描述符。offset参数指定从读入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置。count参数指定在文件描述符in_fd和out_fd之间传输的字节数,失败返回-1并设置errno。
该函数man手册明确指出,in_fd必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道;而out_fd则必须是一个socket。由此可见sendfile几乎专门为在网络上传输文件而设计的。

sendfile传送文件为什么是“零拷贝”?

用普通方法传送文件时,首先要循环调用read和write

  • 系统调用read产生一个上下文切换,从用户态切换到内核态,然后DMA执行拷贝,把文件数据从硬盘读到一个kernel buffer中。
  • 数据从内核态拷贝到用户态,系统调用read返回
  • 系统调用write,从用户态切换到内核态,把用户态的数据拷贝到内核态
  • 从内核态切换到用户态,然后DMA从内核缓冲区拷贝数据到协议栈

    每次read和write要经过4次用户态和内核态之间的切换,系统调用开销大,传送速率慢。并且对于传送文件来说,我们只要知道文件存在,直接发送给对端,而不需要对文件进行读取,sendfile应用而生…

  • 系统调用sendfile,通过DMA 把硬盘数据拷贝到内核缓冲区,然后数据被内核直接拷贝到另外一个socket相关的内核缓冲区中。这里没有用户态和内核态之间的切换,在内核中直接完成了数据从一个内核缓冲区拷贝到另一个内核缓冲区。

  • DMA把数据从内核缓冲区拷贝到协议栈
原创粉丝点击