在apache,nginx,lighttpd等webserver其中,都有一项sendfile相关的配置,在一些网上的资料都有谈到sendfile会提升文件传输性能,那sendfile究竟是什么呢?它的原理又是怎样呢?



在传统的文件传输里面(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到相关协议引擎。

一般来说一个网络应用是通过读硬盘数据,然后写数据到 socket 来完毕网络传输的。上面2行用代码解释了这一点,只是上面2行简单的代码掩盖了底层的非常多操作。来看看底层是怎么运行上面2行代码的:

1、系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 运行拷贝,把文件数据从硬盘读到一个 kernel buffer 里。

2、数据从 kernel buffer 复制到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode。

3、系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后把步骤2读到 user buffer 的数据复制到 kernel buffer(数据第2次复制到 kernel buffer),只是这次是个不同的 kernel buffer,这个 buffer 和 socket 相关联。

4、系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换了),然后 DMA 从 kernel buffer 拷贝数据到协议栈(第4次拷贝了)。

上面4个步骤有4次上下文切换,有4次拷贝,我们发现假设能降低切换次数和拷贝次数将会有效提升性能。在kernel 2.0+ 版本号中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能降低切换次数并且还能降低拷贝次数。

以上细节是传统read/write方式进行网络文件传输的方式,我们能够看到,在这个过程其中,文件数据实际上是经过了四次copy操作:

硬盘—>内核buf—>用户buf—>socket相关缓冲区—>协议引擎



而sendfile系统调用则提供了一种降低以上多次copy,提升文件传输性能的方法。Sendfile系统调用是在2.1版本号内核时引进的:

  1. sendfile(socket, file, len);

执行流程例如以下:

1、sendfile系统调用,文件数据被copy至内核缓冲区

2、再从内核缓冲区copy至内核中socket相关的缓冲区

3、最后再socket相关的缓冲区copy到协议引擎



相较传统read/write方式,2.1版本号内核引进的sendfile已经降低了内核缓冲区到user缓冲区,再由user缓冲区到socket相关缓冲区的文件copy,而在内核版本号2.4之后,文件描写叙述符结果被改变,sendfile实现了更简单的方式,系统调用方式仍然一样,细节与2.1版本号的不同之处在于,当文件数据被拷贝到内核缓冲区时,不再将全部数据copy到socket相关的缓冲区,而是只将记录数据位置和长度相关的数据保存到socket相关的缓存,而实际数据将由DMA模块直接发送到协议引擎,再次降低了一次copy操作。

linux内核系统调用--sendfile函数的更多相关文章

  1. Linux内核-系统调用

    Linux内核-系统调用 1.与内核通信 #系统调用在用户空间进程和硬件设备之间添加了一个中间层 作用:1.为用户空间提供了一种硬件的抽象接口 2.系统调用保证了系统的稳定和安全 3.出于每一个进程都 ...

  2. Linux内核的ioctl函数学习

    Linux内核的ioctl函数学习 来源:Linux公社  作者:Linux 我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围.为什 ...

  3. 举例跟踪linux内核系统调用

    学号351+ 原创作品转载请注明出处 + 中科大孟宁老师的linux操作系统分析: https://github.com/mengning/linuxkernel/ 实验要求: 编译内核5.0 qem ...

  4. Linux内核中kzalloc函数详解

    **************************************************************************************************** ...

  5. linux内核追踪——find_next_bit函数详详详解

    写在前面 宗旨:把话说清楚,把道理讲透彻. 约定:所有代码均来自Linux内核2.6.24版. 建议:本文介绍得十分详细,但也略显繁琐,读者可以先看“Ⅴ.总结”部分带注释的源码,如果哪里不清楚,再回头 ...

  6. linux内核申请内存函数

    kmap函数:    把某块高端内存映射到页表,然后返回给用户一个填好vitual字段的page结构    建立永久地址映射,不是简单的返回virtual字段的pageioremap:    驱动程序 ...

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

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

  8. linux 内核态调试函数BUG_ON()[转]

    一些内核调用可以用来方便标记bug,提供断言并输出信息.最常用的两个是BUG()和BUG_ON(). 当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印.为什么这些声明会导致 oops跟 ...

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

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

随机推荐

  1. 数矩形(N - 暴力求解、打表)

    数矩形 Description 给你一个高为n ,宽为m列的网格,计算出这个网格中有多少个矩形,下图为高为2,宽为4的网格.            Input 第一行输入一个t, 表示有t组数据,然后 ...

  2. c++ ,protected 和 private修饰的构造函数

    c++ protected 和 private修饰的构造函数: 1.在类的外部创建对象时,不能调用protected或private修饰的构造函数. 2.当子类中的构造函数调用父类的private构造 ...

  3. BZOJ 1911: [Apio2010]特别行动队( dp + 斜率优化 )

    sum为战斗力的前缀和 dp(x) = max( dp(p)+A*(sumx-sump)2+B*(sumx-sump)+C )(0≤p<x) 然后斜率优化...懒得写下去了... ------- ...

  4. 【转】管理员必备的Linux系统监控工具

    原文连接: 管理员必备的Linux系统监控工具 #1: top - 进程活动 top提供一个当前运行系统实时动态的视图,也就是正在运行进程.在默认情况下,显示系统中CPU使用率最高的任务,并每5秒钟刷 ...

  5. d3.js入门1:安装配置

    D3 是当前流行的数据可视化工具,通过本文能有对 D3 有一个初步认识. 1. D3 是什么 D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档.听名 ...

  6. Automake创建项目

    autoconf和automake可以方便的构建linux下项目,一个简单的automake项目实例,麻雀虽小五脏俱全,以后无外乎在这基础上扩展相应的宏完善而已. .首先建立项目目录树 )创建目录树 ...

  7. guozhongCrawler的是一个无须配置、便于二次开发

    guozhongCrawler的是一个无须配置.便于二次开发的爬虫开源框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫.模块化设计完全 面向业务提供接口,功能覆盖整个爬虫的生命周期(链接提取 ...

  8. 基于visual Studio2013解决C语言竞赛题之0523魔方阵

     题目

  9. 【Android LibGDX游戏引擎开发教程】第06期:图形图像的绘制(下)图片整合工具的使用

    在上一篇文章中,我们提到了图片必须是2的n次方的问题.但是随着Libgdx的不断完善和发展,使用一些工具就 可以很好的解决了这样一个问题,但是它的功能又不仅仅只限于此,那么下面就来让我们看看Textu ...

  10. Oracle中查询各种对象的方法小结

    --查看当前库中的所有表select * from all_tables a where a.table_name='INFOCODE_P20081'--查看表结构select * from all_ ...