大家好,又见面了,我是你们的朋友全栈君。
配置语法
语法: sendfile on | off;
默认值: sendfile off;
上下文: http,server,location,if in location
说明
sendfile值为on,指定使用sendfile系统调用来传输文件。
sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝。
示例
http {
# ...
sendfile on;
# ...
}
原理
read/write
在传统的文件传输方式(read、write/send方式),具体流程细节如下:
- 调用read函数,文件数据拷贝到内核缓冲区
- read函数返回,数据从内核缓冲区拷贝到用户缓冲区
- 调用write/send函数,将数据从用户缓冲区拷贝到内核socket缓冲区
- 数据从内核socket缓冲区拷贝到协议引擎中
在这个过程当中,文件数据实际上是经过了四次拷贝操作:
硬盘—>内核缓冲区—>用户缓冲区—>内核socket缓冲区—>协议引擎
sendfile
sendfile系统调用则提供了一种减少拷贝次数,提升文件传输性能的方法。
- sendfile系统调用利用DMA(直接存储器访问:外部设备不通过CPU而直接与系统内存交换数据的接口技术)将数据拷贝到内核缓冲区,之后数据被拷贝到与socket相关的内核缓冲区。这里没有 用户态和核心态 之间的切换,在内核中直接完成了从一个 buffer 到另一个 buffer 的拷贝
- DMA擎将数据从内核socket缓冲区拷贝到协议引擎中
这里没有用户态和内核态之间的切换,也没有内核缓冲区和用户缓冲区之间的拷贝,大大提升了传输性能。
这个过程数据经历的拷贝操作如下:
硬盘—>内核缓冲区—>内核socket缓冲区—>协议引擎
带有DMA收集拷贝功能的sendfile
对于带有DMA收集拷贝功能的sendfile系统调用,还可以再减少一次内核缓冲区之间的拷贝。具体流程如下:
- dfile系统调用利用DMA引擎将文件数据拷贝到内核缓冲区,之后,将带有文件位置和长度信息的缓冲区描述符添加到内核socket缓冲区中
- 引擎会将数据直接从内核缓冲区拷贝到协议引擎中
这个过程数据经历的拷贝操作如下:
硬盘—>内核缓冲区—>协议引擎
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/145942.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...