首页 > 其他分享 >sendfile 系统调用

sendfile 系统调用

时间:2022-10-10 17:34:43浏览次数:62  
标签:sendfile 文件大小 调用 系统 TCP CORK fd Nagle

 

Linux "零拷贝" sendfile函数中文说明及实际操作分析

 Sendfile函数说明

  #include <sys/sendfile.h> ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);   sendfile()是作用于数据拷贝在两个文件描述符之间的操作函数.这个拷贝操作是内核中操作的,所以称为"零拷贝".sendfile函数比起read和write函数高效得多,因为read和write是要把数据拷贝到用户应用层操作.   参数说明: out_fd 是已经打开了,用于写操作(write)的文件描述符; in_fd 是已经打开了,用于读操作(read)的文件描述符; offset 偏移量;表示sendfile函数从in_fd中的哪一偏移量开始读取数据.如果是零表示从文件的开始读,否则从相应的便宜量读取.如果是循环读取的时候,下一次offset值应为sendfile函数返回值加上本次的offset的值. count是在两个描述符之间拷贝的字节数(bytes)   返回值: 如果成功的拷贝,返回写操作到out_fd的字节数,错误返回-1,并相应的设置error信息.   EAGAIN 无阻塞I/O设置O_NONBLOCK时,写操作(write)阻塞了. EBADF 输出或者输入的文件描述符没有打开. EFAULT 错误的地址. EINVAL 描述符不可用或者锁定了,或者用mmap()函数操作的in_fd不可用. EIO 当读取(read)in_fd时发生未知错误. ENOMEM 读(read)in_fd时内存不足.   ------------------------------------------------------------------------------   由于想再提升原有系统中文件传输模块的速度,并减少系统资源占用,进行了一次sendfile()的性能测试,但失败了.不过还是将它用在了模块中.记录一下这次失改的微调测试.   运行平台: 客户机与服务器均为P4计算机,IDE硬盘; Fedora5发行版; 百兆局域网;   接收端程序如下:

  FILE *fp = fopen(FILENAME,"wb");

  while((len = recv(sockfd, buff, sizeof(buff), 0)) > 0)
  {
      fwrite(buffer, 1, len, fp);
  }
  fclose(fp);

    A. 发送端传统方式代码段如下:
  fd = open(FILENAME, O_RDONLY);
  while((len =read(fd, buff, sizeof(buff))) >0) 
  {
       send(sockfd, buff, len ,0);
  }
  close(fd);  

由于我磁盘分区时指定的块大小为4096,为了最优读取磁盘数据,buff大小设为4096字节.但在测试中发现设为1024或8192不会对传输速度带来影响.

文件大小:9M; 耗时:0.71 - 0.76秒;
文件大小:32M; 耗时:2.64 - 2.68秒;
文件大小:64M; 耗时:5.36 - 5.43秒;

B. 使用sendfile()传输代码段.

  off_t offset = 0;
  stat(FILENAME, &filestat);

  fd = open(FILENAME, O_RDONLY);
  sendfile(sockfd, fd, &offset, filestat.st_size) );
  close(fd);  

文件大小:9M; 耗时:0.71 - 1.08秒;
文件大小:32M; 耗时:2.66 - 2.74秒;
文件大小:64M; 耗时:5.43 - 6.64秒;

似乎还略有下降.根据sendfile的man手册,我在使用该函数前调用了

 int no = 1;
 printf("%d\n", setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, (char*)&no, sizeof(int)) );

文件大小:9M; 耗时:0.72 - 0.75秒;
文件大小:32M; 耗时:2.66 - 2.68秒;
文件大小:64M; 耗时:5.38 - 5.60秒;

这样似乎达到了传统方式的速度?!不管哪种环境下,我用ethereal抓包显示每一个tcp包的playload部分最大也通常是1448字节.

看来我的测试没有体现出"应用层数据的两次拷贝带来很大的消耗"这一说法.如果按照存在就是有理的说法的话,那我想sendfile()在两种情况下才体现优势,但我却没有环境测试:
1. 大并发量的文件服务器或HTTP服务器;
2. 内存资源紧张的嵌入式系统;

另外,网络上大量的关于tcp选项中的TCP_CORK描述已经过时.在man手册中早已提到该参数可以与TCP_NODELAY结合使用了.只是,只要设置了TCP_NODELAY选项后,不管是否设置TCP_CORK,包都会立即发出.

----------------------------------------------------------------------

补充:

TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。 John Nagle是Nagle算法的发明人,后者就是用他的名字来命名的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就是所谓的silly window syndrome ,中文称“愚蠢窗口症候群”,具体含义是,因为普遍终端应用程序每产生一次击键操作就会发送一个包,而典型情况下一个包会拥有一个字节的数据载荷以及40个字节长的包头,于是产生4000%的过载,很轻易地就能令网络发生拥塞,。 Nagle化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为缺省配置了,但在我们看来,有些场合下把这一选项关掉也是合乎需要的。

现在让我们假设某个应用程序发出了一个请求,希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。例如,当我们正在发送一个较短的请求并且等候较大的响应时,相关过载与传输的数据总量相比就会比较低,而且,如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY选项来完成,这样就禁用了 Nagle算法。

另外一种情况则需要我们等到数据量达到最大时才通过网络一次发送全部数据,这种数据传输方式有益于大量数据的通信性能,典型的应用就是文件服务器。应用Nagle算法在这种情况下就会产生问题。但是,如果你正在发送大量数据,你可以设置TCP_CORK选项禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就让我们仔细分析下其工作原理。

假设应用程序使用sendfile()函数来转移大量数据。应用协议通常要求发送某些信息来预先解释数据,这些信息其实就是报头内容。典型情况下报头很小,而且套接字上设置了TCP_NODELAY。有报头的包将被立即传输,在某些情况下(取决于内部的包计数器),因为这个包成功地被对方收到后需要请求对方确认。这样,大量数据的传输就会被推迟而且产生了不必要的网络流量交换。

但是,如果我们在套接字上设置了TCP_CORK(可以比喻为在管道上插入“塞子”)选项,具有报头的包就会填补大量的数据,所有的数据都根据大小自动地通过包传输出去。当数据传输完成时,最好取消TCP_CORK 选项设置给连接“拔去塞子”以便任一部分的帧都能发送出去。这同“塞住”网络连接同等重要。

总而言之,如果你肯定能一起发送多个数据集合(例如HTTP响应的头和正文),那么我们建议你设置TCP_CORK选项,这样在这些数据之间不存在延迟。能极大地有益于WWW、FTP以及文件服务器的性能,同时也简化了你的工作。

转自:
http://blog.chinaunix.net/u2/76292/showart.php?id=2105375

 

 

参考:

http://www.cppblog.com/beautykingdom/archive/2009/11/28/102185.html

标签:sendfile,文件大小,调用,系统,TCP,CORK,fd,Nagle
From: https://www.cnblogs.com/rebrobot/p/16776527.html

相关文章

  • AF协议DF协议以及无协作的系统误码率仿真分析对比
    clc;clear;closeall;xindao_SD=2;xindao_SR=1;xindao_RD=1.5;M=16;%10种发射信噪比情况R=2;SNR_S=zeros(1,M);%源发射信噪比数组SNR=zeros(1,M);%......
  • 机械手控制系统特点介绍 伺服
    工业机械手是辅助用于自动化生产设备作业的一种替代人工的装置,可以通过编程来控制设备的运行,按照设定好的程序实现预期作业,在注塑、机床、码垛等自动化生产场景中有着广泛的......
  • 基于EDA技术的频率计系统设计
    频率计的基本原理是用一个频率稳定度高的频率源作为基准时钟,对比测量其他信号的频率。通常情况下计算每秒内待测信号的脉冲个数,此时我们称闸门时间为1秒。闸门时间也可以大......
  • 数字通信系统
    PCM抽样的MATLAB程序设计按如下步骤进行:(1)确定输入的模拟信号为sa(200t);(2)根据输入的模拟信号,确定抽样频率,对输入信号进行抽样,并将正常抽样和会产生失真的抽样进行对比,对抽样......
  • 墨门云文件加密系统有哪些功能特点?
    墨门云文件加密系统采用高性能透明加密内核技术,是一个从源头上保障企业数据安全的安全管理系统。透明加解密技术:当使用者在打开或编辑指定文件时,系统将自动对未加密的文件进......
  • 智能CDN(中):CDN的系统构成和核心技术
    CDN的系统构成CDN的系统构成具体如下表:表1CDN的系统构成CDN的核心技术一、内容路由(负载均衡技术)每个CDN节点层都配备智能DNS服务器,即负载均衡设备,其作用是使Cache......
  • 系统安全
    一、账号安全基本措施1、系统账号清理1.1将非登录用户的Shell设为/sbin/nologinusermod-s /sbin/nologin 用户名1.2锁定长期不使用的账号usermod-Lmcl  ......
  • linux操作系统防火墙
      Centos6,Centos7启动服务命令对比Centos6:对于Centos6系统来说,直接使用chkconfig命令即可。例如我们以nginx服务为例:chkconfig--addnginx#添加ng......
  • DTMF信号系统的Matlab仿真
        双音多频(DualToneMultiFrequency,DTMF)信号是音频电话中的拨号信号,由美国AT&T贝尔公司实验室研制,并用于电话网络中。这种信号制式具有很高的拨号速度,且容易......
  • 基带传输系统的简介和研究的意
    1.1 研究的意义由于基带传输系统在数字传输系统中有不可替代的作用,其应用范围也随着技术的发展渗入网络通信、卫星通信及测控、手机通信、数字电视、数字电话等生活、科技......