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

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

in_fd参数是待读出内容的文件描述符,out_fd参数是待写入内容的文件描述符。offset参数指定从读入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置。count参数指定文件描述符in_fd和out_fd之间传输的字节数。

in_fd必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道,而out_fd必须是一个socket

首先我们来看看传统的read/write方式进行socket的传输。
当需要对一个文件进行传输的时候,具体流程细节如下:

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

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

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

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

在这个过程中发生了四次copy操作。

硬盘->内核->用户->socket缓冲区(内核)->协议引擎。

而sendfile的工作原理呢??

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

测试代码:

#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<string.h>
#include<sys/sendfile.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<errno.h>int main(int argc,char *argv[])
{if(argc<=3){printf("usage:%s ip_address port_number filename\n",basename(argv[0]));return 1;}const char* ip = argv[1];int port = atoi(argv[2]);const char* file_name = argv[3];int filefd = open(file_name,O_RDONLY);assert(filefd>0);struct stat stat_buf;fstat(filefd,&stat_buf);struct sockaddr_in address;bzero(&address,sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET,ip,&address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET,SOCK_STREAM,0);assert(sock>=0);int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));assert(ret!=-1);ret = listen(sock,5);assert(ret!=-1);struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);if(connfd<0){printf("errno is %d\n",errno);}else {sendfile(connfd,filefd,NULL,stat_buf.st_size);close(connfd);}close(sock);return 0;
}

然后进行

在另外一个虚拟机上telnet

高级I/O函数之sendfile函数相关推荐

  1. linux 高级IO函数之sendfile splice tee

    sendfile函数在两个文件描述符之间传递数据(完全在内核中操作),从而避免内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,这被称为零拷贝.函数的定义如下: #include<sys/send ...

  2. python用psf函数_Python 嵌套函数(高级用法)

    Python 嵌套函数(高级用法) 一.嵌套函数(高级用法) 1.嵌套函数 函数的嵌套调用是在"函数调用中再调用其他函数".也就是说:函数嵌套允许在一个函数中调用另外一个函数.如下 ...

  3. JavaScript高级day01-PM【对象、函数、回调函数、IIFE、this、关于语句分号问题、webstorm代码模板、复习】

    笔记.视频.源码:JavaScript(基础.高级)笔记汇总表[尚硅谷JavaScript全套教程完整版] 目   录 P7 07.尚硅谷_JS高级_对象 23:30 1. 什么是对象? 2. 为什么 ...

  4. Linux 零拷贝 sendfile函数中文说明及实际操作

    Sendfile函数说明  #include  ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); sendfi ...

  5. unix环境高级编程之 read与write 函数详解

    学习记录:unix环境高级编程之 read 与write  函数详解 备注:本博文非本人所写,本人觉得此文讲的非常地道通俗易懂,所以摘录在此以方便以后再次查看 read函数从打开的设备或文件中读取数据 ...

  6. 第8章 Drupal 主题系统( Drupal theme)(4) 高级特性--1,覆写主题函数

    Drupal主题高级特性  译者:老葛 在前面的部分,你学到了Drupal使用的各种不同模板文件,当Drupal要将你的主题合并到一起时就会查找这些模板.你学到了如何创建页面模板文件,如何创建特定节点 ...

  7. JavaScript高级第2天:定义函数的三种方式、函数的原型链结构、完整原型链、作用域以及作用域链、函数的四种调用模式、闭包、计数器、斐波那契数列优化、三种继承方式

    JavaScript高级第二天 01-定义函数的三种方式 1.函数声明 function:可以先调用再声明,因为预解析(把函数声明.变量声明进行提升) function fn() {//函数体conl ...

  8. Hive学习---4、函数(单行函数、高级聚合函数、炸裂函数、窗口函数)

    1.函数 1.1 函数简介 Hive会将常用的逻辑封装成函数给用户进行使用,类似java中的函数. 好处:避免用户反复写逻辑,可以直接拿来使用 重点:用户需要知道函数叫什么,能做什么 Hive提供了大 ...

  9. js高级第一章--变量提升,函数提升

    js高级第一章–变量提升,函数提升 文章目录 前言 一.什么是js里的提升? 二.js变量提升 三.js函数提升 四.特殊情况 总结 前言 在js中,最基本的声明方式有三种,即:var,let,con ...

最新文章

  1. rda8955平台搭建摘要截图
  2. [ 搞笑 ] 疯狂的石头与张柏芝
  3. python中 for ... else ... 的用法
  4. MongoDB 进阶-关联查询
  5. Django 模板中使用css, javascript
  6. .Net转Java自学之路—基础巩固篇八—总结(封装、继承、多态)
  7. GitLab CI 自动部署netcore web api 到Docker
  8. 如何使处于不同局域网的计算机实现远程通信_小区自来水二次加压泵站远程监控系统方案...
  9. redis数据持久化到mysql_redis 数据持久化的几种方式
  10. 位运算在一类数组题中的用法 只出现一次的数字I
  11. PHP 发送HTTP post请求发送和获取
  12. 3.3 修改“时间”维度
  13. vue学习(十五) 过滤器简单实用
  14. 卡巴斯基2013简体中文正式版
  15. 笔记本一接上HDMI转VGA转换器就黑屏,无法操作连接显示器
  16. linux系统声卡安装教程,Linux操作系统声卡驱动的安装与配置
  17. 微信公众开发 表情开发php,微信开发Emoji表情的实例教程
  18. 引用计数与可达性分析
  19. 基于SSM的毕业论文管理系统
  20. java中items是什么意思,Ansible - 如何使用with_items中的寄存器名称

热门文章

  1. Android APP安全测试Checklist
  2. 2022南宁高新区招聘社区戒毒(康复)工作人员仿真试题及答案
  3. css 水平翻转和垂直翻转
  4. 4 交换机划分vlan配置
  5. linux tkinter安装,Python的Tkinter库的安装--Debian
  6. 一次性讲透利率变化对投资的影响
  7. 15款最好的Windows系统安全检测工具
  8. 成功打开笔记本的摄像头
  9. 摘:轻而易举拥有xp风格的界面
  10. messenger支持查找附近的人功能吗_可以查找附近的人那个软件叫什么?