(转)Nginx中sendfile的做用

原文:https://blog.csdn.net/zhusixun/article/details/81702380web

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。
本文连接:https://blog.csdn.net/zhusixun/article/details/81702380
那么sendfile是什么东西,他是怎么影响性能的… …  sendfile其实是 Linux2.0+之后的推出的一个系统调用,web服务器能够经过调整自身的配置来决定是否利用 sendfile这个系统调用。先来看一下不用 sendfile的传统网络传输过程:服务器

read(file,tmp_buf, len);网络

write(socket,tmp_buf, len);socket

硬盘 >> kernel buffer >> user buffer>> kernel socket buffer >>协议栈函数


标题
一个基于socket的服务,首先读硬盘数据,而后写数据到socket 来完成网络传输的。上面2行用代码解释了这一点,不过上面2行简单的代码掩盖了底层的不少操做。来看看底层是怎么执行上面2行代码的:性能

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

二、数据从 kernel buffer拷贝到 user buffer,而后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode。代理

三、 系统调用write()产生一个上下文切换:从 user mode切换到 kernel mode,而后把步骤2读到 user buffer的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过此次是个不一样的 kernel buffer,这个 buffer和 socket相关联。blog

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

上面4个步骤有4次上下文切换,有4次拷贝,咱们发现若是能减小切换次数和拷贝次数将会有效提高性能。在kernel2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提高性能的。sendfile() 不但能减小切换次数并且还能减小拷贝次数。

再来看一下用 sendfile()来进行网络传输的过程:

sendfile(socket,file, len);

硬盘 >> kernel buffer (快速拷贝到kernelsocket buffer) >>协议栈

一、 系统调用sendfile()经过 DMA把硬盘数据拷贝到 kernel buffer,而后数据被 kernel直接拷贝到另一个与 socket相关的 kernel buffer。这里没有 user mode和 kernel mode之间的切换,在 kernel中直接完成了从一个 buffer到另外一个 buffer的拷贝。

二、DMA 把数据从 kernelbuffer 直接拷贝给协议栈,没有切换,也不须要数据从 user mode 拷贝到 kernel mode,由于数据就在 kernel 里。

简单说,sendfile是个比 read 和 write 更高性能的系统接口, 不过须要注意的是,sendfile 是将 in_fd 的内容发送到 out_fd 。而 in_fd 不能是 socket , 也就是只能文件句柄。 因此当 Nginx 是一个静态文件服务器的时候,开启 SENDFILE 配置项能大大提升 Nginx 的性能。 可是当 Nginx 是做为一个反向代理来使用的时候,SENDFILE 则没什么用了,由于 Nginx 是反向代理的时候。 in_fd 就不是文件句柄而是 socket,此时就不符合 sendfile 函数的参数要求了。

相关文章
相关标签/搜索