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. 一种用javascript实现的比较兼容的回到顶部demo + 阻止事件冒泡

    回到页面顶部demo <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  2. 鸟哥私房菜--第1章 Linux 是什么

    [只做搬运工,在搬运的时候窃看其中乐趣.] 历史渊源 Linus Torvalds(请记住这个名字)当年(1991)在写Linux的时候,初衷是针对386型机器的,当时只是一套裸露的操作系统并不包含任 ...

  3. (Problem 7)10001st prime

    By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. ...

  4. Linux下安装jekyll

    折腾了大半天,终于搞定了,这可得记下来了. 我的Linux版本:CentOS 6.5 主要的安装顺序还是官网上的说明:http://jekyllrb.com/docs/installation/,所以 ...

  5. JavaScript 的数组操作--删除元素

    在JavaScript中,可以很方便的删除指定位置的元素,这个是用到 splice方法, 该方法用于删除或替换数组中的部分数据. 其语法定义是 : splice(start , count [,new ...

  6. Android有效解决加载大图片时内存溢出的问题

    首先,您需要了解一下,图片占用内存的计算方法,传送门:http://blog.csdn.net/scry5566/article/details/11568751 尽量不要使用setImageBitm ...

  7. 17.1.1.7 Setting Up Replication with New Master and Slaves 设置复制对于新的Master和Slaves:

    17.1.1.7 Setting Up Replication with New Master and Slaves 设置复制对于新的Master和Slaves: 最简单和最直接的方法是设置复制用于使 ...

  8. C++将文件内容一次性读入内存

    结合字符串流,将文件中的内容一次性读入内存,代码如下: #include <string> using std::ostringstream; using std::ifstream; u ...

  9. PHP - FTP上传文件类

    /** * 作用:FTP操作类( 拷贝.移动.删除文件/创建目录 ) * 时间:2006/5/9 * 作者:欣然随风 * QQ:276624915 */ class class_ftp { publi ...

  10. xp对opengl的支持问题

    我在项目中遇到的xp显示问题是因为xp对opengl的支持问题,是通过void QCoreApplication::setAttribute(Qt::ApplicationAttribute attr ...