linux为了解决对读文件产生的从应用空间到内核空间复制数据产生的效率影响引进了零拷贝。什么是零拷贝?这里就不多说了,请参考http://blog.csdn.net/crazyguang/article/details/2423708,我们主要是讲述nginx怎么是用sendfile的。

nginx通过使用sendfile指令来控制是不是用linux提供的零拷贝功能。具体配置如下:

sendfile on/off

注:这个指令只能用在HTTP框架下。
上面指令的作用就是给struct ngx_http_core_loc_conf_s 的sendfile赋值,逻辑也比较简单。

下面以nginx做源服务来讲述这个功能。nginx做源服务都会通过ngx_http_static_handler讲url转换成文件的目录(ngx_http_map_uri_to_path)。

static ngx_int_t
ngx_http_static_handler(ngx_http_request_t *r)
{
......
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
......
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
......
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
b->file_pos = 0;
b->file_last = of.size; b->in_file = b->file_last ? 1: 0;
b->last_buf = (r == r->main) ? 1: 0;
b->last_in_chain = 1; b->file->fd = of.fd;
b->file->name = path;
b->file->log = log;
b->file->directio = of.is_directio; out.buf = b;
out.next = NULL; return ngx_http_output_filter(r, &out);
......
}

通过 ngx_http_map_uri_to_path找到路径后就会调用ngx_open_cached_file打开文件,并获取到文件的相关信息。下面创建一个buf,注意这个buf的初始化在后面会用到。ngx_http_output_filter进入到filter链中。最后会调用到ngx_http_copy_filter。

static ngx_int_t
ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
......
ctx->sendfile = c->sendfile;
ctx->need_in_memory = r->main_filter_need_in_memory
|| r->filter_need_in_memory;
ctx->need_in_temp = r->filter_need_temporary;
for ( ;; ) {
rc = ngx_output_chain(ctx, in);
......
}

注意ctx->sendfile的值也是非要重要的。

ngx_int_t
ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
{
......
if (in->next == NULL
#if (NGX_SENDFILE_LIMIT)
&& !(in->buf->in_file && in->buf->file_last > NGX_SENDFILE_LIMIT)
#endif
&& ngx_output_chain_as_is(ctx, in->buf))
{
return ctx->output_filter(ctx->filter_ctx, in);
}
......
} static ngx_inline ngx_int_t
ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
{
......
if (!sendfile) { if (!ngx_buf_in_memory(buf)) {
return 0;
} buf->in_file = 0;
}
......
}

这里面sendfile和buf中in_file就是判断数据是不是在文件中。如果上面的判断为真就会直接调用发送函数(ngx_linux_sendfile_chain),要不然就会调用ngx_output_chain_copy_buf把数据从文件中读取出来。

讲到现在也没讲到sendfile指令是怎么影响nginx是否使用linux的零拷贝的。上面代码中其中有一段是这样的:
ctx->sendfile = c->sendfile
前面讲过sendfile会影响是否读取文件内容,而这个sendfile就是ctx->sendfile的值。那c->sendfile,我们来看下ngx_http_update_location_config:
void
ngx_http_update_location_config(ngx_http_request_t *r)
{
......
if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
r->connection->sendfile = 1; } else {
r->connection->sendfile = 0;
}
......
}

到这里就能理解了sendfile怎么影响nginx的sendfile处理了。下面来看最后一个函数, ngx_linux_sendfile_chain

ngx_chain_t *
ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
......
if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) {
file = cl->buf;
......
if (file) {
......
rc = sendfile(c->fd, file->file->fd, &offset, file_size);
......
} else {
rc = writev(c->fd, header.elts, header.nelts);
......
}

可以看出如果file有值就会调用sendfile,但是在上面的if语句中cl->buf->in_file在前面判断是否读取文件内容的时候会进行修改,也就是如果要读取文件内容就会复位0,这样读取了文件内容后就直接调用writev发送数据,否则就调用sendfile发送文件到客户端。

nginx的sendfile指令的作用的更多相关文章

  1. linux中test与[ ]指令的作用

    linux中test与[ ]指令的作用: 在Linux中,test和[ ]功能是一样的,类似于c语言中的( ).不过Linux的test和[ ]是指令.在和if或者while联用时要用空格分开.

  2. nginx:location指令中的正则表达式

    nginx:location指令中的正则表达式 uri匹配步骤 官网说明https://docs.nginx.com/nginx/admin-guide/web-server/web-server/ ...

  3. (转)nginx日志配置指令详解

    这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...

  4. nginx 配置优化指令

    worker_processes worker_processes指令是用来设计Nginx进程数,官方默认设为1,赋值太多了,将会对系统IO影响效率,降低Nginx服务器性能.但是为了让多核CPU能够 ...

  5. nginx日志配置指令详解

    这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...

  6. [Linux] nginx的try_files指令实现隐藏index.php的重写

    1.nginx的try_files指令 ,核心功能是替代rewrite,并且比rewrite更强大的是可以按顺序查找文件是否存在,如果文件都找不到才会执行最后的重定向解决的问题是,如果一个网站的部署是 ...

  7. Python的global指令的作用

    Python的global指令的作用 学过其他常用编程语言的同学一定清楚,Python是一个语法非常宽容的语言.它是个变量的定义可以省略.直接赋值.根据赋值结果自动确定变量类型的弱类型语言. 但是这样 ...

  8. vue第十三单元(指令的作用,指令的钩子函数)

    第十三单元(指令的作用,指令的钩子函数) #课程目标 1.了解自定义指令的应用场景 2.掌握自定义全局和局部指令 3.掌握指令的钩子函数 #知识点 #一.认识自定义指令 除了核心功能默认内置的指令 ( ...

  9. Nginx的mirror指令能干啥?

    mirror 流量复制 Nginx的 mirror 指令来自于 ngx_http_mirror_module 模块 Nginx Version > 1.13.4 mirror 指令提供的核心功能 ...

随机推荐

  1. 【转】centos安装memcached+php多服务器共享+session多机共享问题

    参考博文: centos安装memcached 源码安装 Yum安装Memcache Memcached内存分配优化及使用问题 <转>php+memcached 实现session共享 P ...

  2. poj 3370 鸽笼原理知识小结

    中学就听说过抽屉原理,可惜一直没机会见识,现在这题有鸽笼原理的结论,但其实知不知道鸽笼原理都可以做 先总结一下鸽笼原理: 有n+1件或n+1件以上的物品要放到n个抽屉中,那么至少有一个抽屉里有两个或两 ...

  3. 基于visual Studio2013解决算法导论之052深度优先

     题目 深度优先 解决代码及点评 // 深度优先.cpp : 定义控制台应用程序的入口点. // // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include < ...

  4. TCP和UDP的"保护消息边界" (经典)

    在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有 ...

  5. POJ1700(过河问题)

    #include<iostream> #include<algorithm> using namespace std; ]; int main() { int t,i; cin ...

  6. [转]PostgreSQL事务处理机制

    原文链接:http://blog.chinaunix.net/uid-20726500-id-4040024.html 事务的实现原理可以解读为DBMS采取何种技术确保事务的ACID特性.Postgr ...

  7. 我的Python成长之路---第一天---Python基础(6)---2015年12月26日(雾霾)

    七.列表——list Python的列表是一种内置的数据类型,是由Python的基本数据类型组成的有序的集合.有点类似C语言的数组,但与数组不同的是,Python在定义列表的时候不用指定列表的容积(长 ...

  8. C--全排列的实现(递归方法) 傻子也能看懂的

      假设数组含有n个元素,则提取数组中的每一个元素做一次头元素,然后全排列除数组中除第一个元素之外的所有元素,这样就达到了对数组中所有元素进行全排列的得目的.[这句话才是重点!] 比如 1,2,3.的 ...

  9. win10 系统下获取系统版本号为6.2的问题(manifest如何写)

    近期赶时髦升级了win10,用着挺爽.但是某天在测试一个bug时发现要对win10做特殊处理,于是直接调用了GetVersionEx,并取出版本号进行判断,但是发现得到的版本竟然是6.2.当时就被雷到 ...

  10. PHP - 使用pear的HTTP_Upload包进行上传

    前台代码: <html> <head> <title>上传文件</title> </head> <body> <form ...