Nginx服务器中的模块编写及相关内核源码初探_nginx

1.nginx模块
首先nginx和apache最大的不同就是nginx的模块不能够动态添加,需要在编译时,指定要添加的模块路径,与nginx源码一起编译。
nginx模块的处理流程:
a.客户端发送http请求到nginx服务器
b.nginx基于配置文件中的位置选择一个合适的处理模块
c.负载均衡模块选择一台后端服务器(反向代理情况下)
d.处理模块进行处理并把输出缓冲放到第一个过滤模块上
e.第一个过滤模块处理后输出给第二个过滤模块
f.然后第二个过滤模块又到第三个过滤模块
g.第N个过滤模块。。。
h.处理结果发给客户端

2.nginx模块编写
a、创建模块文件夹

mkdir -p /opt/nginx_hello_world
cd /op/nginx_hello_word

b、创建模块配置文件

vi /opt/nginx_hello_word/config

c、创建模块主文件

vi /opt/nginx_hello_world/ngx_http_hello_world_module.c

写入如下内容:

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h> 

static char *ngx_http_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

写的helloworld模块 
  
 

/* Commands */
static ngx_command_t ngx_http_hello_world_commands[] = {
 { ngx_string("hello_world"),
  NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
  ngx_http_hello_world,
  0,
  0,
  NULL },
 ngx_null_command
}; 

static u_char ngx_hello_world[] = "hello world"; 

static ngx_http_module_t ngx_http_hello_world_module_ctx = {
 NULL,         /* preconfiguration */
 NULL,          /* postconfiguration */
 NULL,         /* create main configuration */
 NULL,         /* init main configuration */
 NULL,         /* create server configuration */
 NULL,         /* merge server configuration */
 NULL,         /* create location configuration */
 NULL         /* merge location configuration */
};
/* hook */
ngx_module_t ngx_http_hello_world_module = {
 NGX_MODULE_V1,
 &ngx_http_hello_world_module_ctx,    /* module context */
 ngx_http_hello_world_commands,     /* module directives */
 NGX_HTTP_MODULE,      /* module type */
 NULL,         /* init master */
 NULL,         /* init module */
 NULL,    /* init process */
 NULL,         /* init thread */
 NULL,         /* exit thread */
 NULL,    /* exit process */
 NULL,         /* exit master */
 NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_http_hello_world_handler(ngx_http_request_t *r)
{
 ngx_int_t  rc;
 ngx_buf_t *b;
 ngx_chain_t out;
 /* Http Output Buffer */
 r->headers_out.content_type.len = sizeof("text/plain") - 1;
 r->headers_out.content_type.data = (u_char *) "text/plain"; 

 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); 

 out.buf = b;
 out.next = NULL; 

 b->pos = ngx_hello_world;
 b->last = ngx_hello_world + sizeof(ngx_hello_world);
 b->memory = 1;
 b->last_buf = 1; 

 r->headers_out.status = NGX_HTTP_OK;
 r->headers_out.content_length_n = sizeof(ngx_hello_world);
 ngx_http_send_header(r); 

 return ngx_http_output_filter(r, &out);
}
static char *
ngx_http_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
 ngx_http_core_loc_conf_t *clcf ;
 /* register hanlder */
 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 clcf->handler = ngx_http_hello_world_handler;
 return NGX_CONF_OK;
}

d、下载nginx源码包,我下载的是nginx-1.0.13.tar.gz
这里注意在编译helloworld模块前首先确认,nginx是否可以独立编译成功,是否安装了所需的所有模块。
与helloworld模块一起编译nginx:

./configure --prefix=/usr/local/nginx --add-module=/opt/nginx_hello_world/
make
make install

e、配置nginx.conf

location= /hello {
 hello_world;
}

f、启动nginx,访问http://localhost/hello ,可以看到编写的helloworld模块输出的文字。
 
3.hello world模块分析
a.ngx_command_t函数用于定义包含模块指令的静态数组ngx_http_hello_world_commands

static ngx_command_t ngx_http_hello_world_commands[] = {
 { ngx_string("hello_world"), //设置指令名称字符串,注意不能包含空格,数据类型ngx_str_t之后会详细讲解。
  NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, //配置指令的合法位置,这里表示:location部分合法,并且指令没有参数。
  ngx_http_hello_world,//回调函数,三个参数(ngx_conf_t *cf,ngx_command_t *cmd, void *conf)
  0,//后面的参数有待发掘,我还没有用到
  0,
  NULL },
 ngx_null_command
};

b.static u_char ngx_hello_world[] ="hello world" 则是输出到屏幕的字符串。
c.ngx_http_module_t用来定义结构体ngx_http_hello_world_module_ctx:

static ngx_http_module_t ngx_http_hello_world_module_ctx = {
 NULL,         /* 读入配置前调用*/
 NULL,          /* 读入配置后调用*/
 NULL,         /* 创建全局部分配置时调用 */
 NULL,         /* 初始化全局部分的配置时调用*/
 NULL,         /* 创建虚拟主机部分的配置时调用*/
 NULL,         /* 与全局部分配置合并时调用 */
 NULL,         /* 创建位置部分的配置时调用 */
 NULL         /* 与主机部分配置合并时调用*/
};

d.ngx_module_t定义结构体ngx_http_hello_world_module

ngx_module_t ngx_http_hello_world_module = {
 NGX_MODULE_V1,
 &ngx_http_hello_world_module_ctx,    /* module context */
 ngx_http_hello_world_commands,     /* module directives */
 NGX_HTTP_MODULE,      /* module type */
 NULL,         /* init master */
 NULL,         /* init module */
 NULL,    /* init process */
 NULL,         /* init thread */
 NULL,         /* exit thread */
 NULL,    /* exit process */
 NULL,         /* exit master */
 NGX_MODULE_V1_PADDING
};

e.处理函数,ngx_http_hello_world_handler,也是hello world 模块的核心部分。

static ngx_int_t
ngx_http_hello_world_handler(ngx_http_request_t *r)//ngx_http_request_t *r
//可以访问到客户端的头部和不久要发送的回复头部
{
 ngx_int_t  rc;
 ngx_buf_t *b;
 ngx_chain_t out;
 /* Http Output Buffer */
 r->headers_out.content_type.len = sizeof("text/plain") - 1;
 r->headers_out.content_type.data = (u_char *) "text/plain"; 

 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); 

 out.buf = b;
 out.next = NULL; 

 b->pos = ngx_hello_world;
 b->last = ngx_hello_world + sizeof(ngx_hello_world);
 b->memory = 1;
 b->last_buf = 1; 

 r->headers_out.status = NGX_HTTP_OK;
 r->headers_out.content_length_n = sizeof(ngx_hello_world);
 ngx_http_send_header(r); 

 return ngx_http_output_filter(r, &out);
}

helloworld模块里面涉及最重要的数据就是ngx_module_t指针数组,这个指针数组包含了当前编译版本支持的所有模块,这个指针数组定义实在自动脚本生成的objs/ngx_modules.c中,如下:

 extern ngx_module_t ngx_core_module;
 extern ngx_module_t ngx_errlog_module;
 extern ngx_module_t ngx_conf_module;
 extern ngx_module_t ngx_events_module;
 extern ngx_module_t ngx_event_core_module;
 extern ngx_module_t ngx_epoll_module;
 extern ngx_module_t ngx_http_module;
 extern ngx_module_t ngx_http_core_module;
 extern ngx_module_t ngx_http_log_module;
 extern ngx_module_t ngx_http_upstream_module;
 extern ngx_module_t ngx_http_static_module;
 extern ngx_module_t ngx_http_autoindex_module;
 extern ngx_module_t ngx_http_index_module;
 extern ngx_module_t ngx_http_auth_basic_module;
 extern ngx_module_t ngx_http_access_module;
 extern ngx_module_t ngx_http_limit_zone_module;
 extern ngx_module_t ngx_http_limit_req_module;
 extern ngx_module_t ngx_http_geo_module;
 extern ngx_module_t ngx_http_map_module;
 extern ngx_module_t ngx_http_split_clients_module;
 extern ngx_module_t ngx_http_referer_module;
 extern ngx_module_t ngx_http_rewrite_module;
 extern ngx_module_t ngx_http_proxy_module;
 extern ngx_module_t ngx_http_fastcgi_module;
 extern ngx_module_t ngx_http_uwsgi_module;
 extern ngx_module_t ngx_http_scgi_module;
 extern ngx_module_t ngx_http_memcached_module;
 extern ngx_module_t ngx_http_empty_gif_module;
 extern ngx_module_t ngx_http_browser_module;
 extern ngx_module_t ngx_http_upstream_ip_hash_module;
 extern ngx_module_t ngx_http_cache_purge_module;
 extern ngx_module_t ngx_http_write_filter_module;
 extern ngx_module_t ngx_http_header_filter_module;
 extern ngx_module_t ngx_http_chunked_filter_module;
 extern ngx_module_t ngx_http_range_header_filter_module;
 extern ngx_module_t ngx_http_gzip_filter_module;
 extern ngx_module_t ngx_http_postpone_filter_module;
 extern ngx_module_t ngx_http_ssi_filter_module;
 extern ngx_module_t ngx_http_charset_filter_module;
 extern ngx_module_t ngx_http_userid_filter_module;
 extern ngx_module_t ngx_http_headers_filter_module;
 extern ngx_module_t ngx_http_copy_filter_module;
 extern ngx_module_t ngx_http_range_body_filter_module;
 extern ngx_module_t ngx_http_not_modified_filter_module; 

 ngx_module_t *ngx_modules[] = {
  &ngx_core_module,
  &ngx_errlog_module,
  &ngx_conf_module,
  &ngx_events_module,
  &ngx_event_core_module,
  &ngx_epoll_module,
  &ngx_http_module,
  &ngx_http_core_module,
  &ngx_http_log_module,
  &ngx_http_upstream_module,
  &ngx_http_static_module,
  &ngx_http_autoindex_module,
  &ngx_http_index_module,
  &ngx_http_auth_basic_module,
  &ngx_http_access_module,
  &ngx_http_limit_zone_module,
  &ngx_http_limit_req_module,
  &ngx_http_geo_module,
  &ngx_http_map_module,
  &ngx_http_split_clients_module,
  &ngx_http_referer_module,
  &ngx_http_rewrite_module,
  &ngx_http_proxy_module,
  &ngx_http_fastcgi_module,
  &ngx_http_uwsgi_module,
  &ngx_http_scgi_module,
  &ngx_http_memcached_module,
  &ngx_http_empty_gif_module,
  &ngx_http_browser_module,
  &ngx_http_upstream_ip_hash_module,
  &ngx_http_cache_purge_module,
  &ngx_http_write_filter_module,
  &ngx_http_header_filter_module,
  &ngx_http_chunked_filter_module,
  &ngx_http_range_header_filter_module,
  &ngx_http_gzip_filter_module,
  &ngx_http_postpone_filter_module,
  &ngx_http_ssi_filter_module,
  &ngx_http_charset_filter_module,
  &ngx_http_userid_filter_module,
  &ngx_http_headers_filter_module,
  &ngx_http_copy_filter_module,
  &ngx_http_range_body_filter_module,
  &ngx_http_not_modified_filter_module,
  NULL
 }; 

 

这里只有每个模块变量的声明,并且每个模块的定义都包含在自己的模块文件当中,比如ngx_core_module定义在src/core/nginx.c中:

ngx_module_t ngx_core_module = {
 NGX_MODULE_V1,
 &ngx_core_module_ctx,     /* module context */
 ngx_core_commands,      /* module directives */
 NGX_CORE_MODULE,      /* module type */
 NULL,         /* init master */
 NULL,         /* init module */
 NULL,         /* init process */
 NULL,         /* init thread */
 NULL,         /* exit thread */
 NULL,         /* exit process */
 NULL,         /* exit master */
 NGX_MODULE_V1_PADDING
}; 

是不是跟helloworld里面非常相似了,没错,他们都是模块,唯一的不同点就是helloworld是你另外加进去的。
到现在位置也只是初探nginx的模块,最后提一张别人画的nginx的模块图,有助于接下来的学习。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索nginx
, 源码
, 内核
模块
nginx内核参数优化、nginx内核、nginx 内核优化、nginx 内核 参数、nginx流媒体服务器,以便于您获取更多的相关知识。

时间: 2024-08-29 11:37:13

Nginx服务器中的模块编写及相关内核源码初探_nginx的相关文章

详解Nginx服务器中map模块的配置与使用_nginx

map指令使用ngx_http_map_module模块提供的.默认情况下,nginx有加载这个模块,除非人为的 --without-http_map_module. ngx_http_map_module模块可以创建变量,这些变量的值与另外的变量值相关联.允许分类或者同时映射多个值到多个不同值并储存到一个变量中,map指令用来创建变量,但是仅在变量被接受的时候执行视图映射操作,对于处理没有引用变量的请求时,这个模块并没有性能上的缺失.一. ngx_http_map_module模块指令说明ma

Nginx服务器中使用gzip压缩的相关配置解析_nginx

gzip压缩使用 gzip 压缩可以降低网站带宽消耗,同时提升访问速度. 主要在nginx服务端将页面进行压缩,然后在浏览器端进行解压和解析, 目前大多数流行的浏览器都迟滞gzip格式的压缩,所以不用担心. 默认情况下,Nginx的gzip压缩是关闭的,同时,Nginx默认只对text/html进行压缩 主要配置如下: gzip on;#开启 gzip_http_version 1.0;#默认1.1 gzip_vary on; gzip_comp_level 6; gzip_proxied an

Nginx服务器中处理AJAX跨域请求的配置方法讲解_nginx

Nginx 实现AJAX跨域请求AJAX从一个域请求另一个域会有跨域的问题.那么如何在nginx上实现ajax跨域请求呢?要在nginx上启用跨域请求,需要添加add_header Access-Control*指令.如下所示: location /{ add_header 'Access-Control-Allow-Origin' 'http://other.subdomain.com'; add_header 'Access-Control-Allow-Credentials' 'true'

Nginx服务器中414错误和504错误的配置解决方法_nginx

414 Request-URI Too Large #客户端请求头缓冲区大小,如果请求头总长度大于小于128k,则使用此缓冲区, #请求头总长度大于128k时使用large_client_header_buffers设置的缓存区 client_header_buffer_size 128k; #large_client_header_buffers 指令参数4为个数,128k为大小,默认是8k.申请4个128k. large_client_header_buffers 4 128k; 当http

使用Lua编写Nginx服务器的认证模块的方法

  这篇文章主要介绍了使用Lua编写Nginx服务器的认证模块的方法,即诸如当今流行的社交应用接入等功能,需要的朋友可以参考下 过去两天里,我解决了一个非常有趣的问题.我用一个nginx服务器作为代理,需要能够向其中添加一个认证层,使其能够使用外部的认证源(比如某个web应用)来进行验证,如果用户在外部认证源有账号,就可以在代理里认证通过. 需求一览 我考虑了几种解决方案,罗列如下: 用一个简单的Python/Flask模块来做代理和验证. 一个使用subrequests做验证的nginx模块(

详解nginx服务器中的安全配置_nginx

本篇文章详细的讲诉了nginx服务器中的安全配置,具体如下: 一.关闭SELinux 安全增强型Linux(SELinux)的是一个Linux内核的功能,它提供支持访问控制的安全政策保护机制. 但是,SELinux带来的附加安全性和使用复杂性上不成比例,性价比不高 sed -i /SELINUX=enforcing/SELINUX=disabled/ /etc/selinux/config /usr/sbin/sestatus -v #查看状态 二.通过分区挂载允许最少特权 服务器上 nginx

虚拟机下Ubuntu找不到USB相关的源码文件

问题描述 虚拟机下Ubuntu找不到USB相关的源码文件 如题,在虚拟机里进入 /usr/src/linux/drivers/usb/core 文件夹中只有Kconfig和Makefile两个文件,没有其他文件.但是直接从官网下载的内核源码的这个路径下是有USB相关的源码的,想问下大神们这是怎么回事.菜鸟万分感激. 解决方案 http://article.yeeyan.org/view/208966/175140 为了能在Ubuntu主机上的虚拟机上访问你的USB设备,你需要把你的用户名加入到v

用C#写了一个SLE4442加密卡充值售电软件,源代码中包含写卡密码,C#源码可用.Net Reflector 反编译的话,那写卡密码岂不是很容易泄露

问题描述 用C#写了一个SLE4442加密卡充值售电软件,源代码中包含写卡密码,C#源码可用.NetReflector反编译的话,那写卡密码岂不是很容易泄露.请问如何解决这个问题.谢谢大家. 解决方案 解决方案二:你的充值售电软件会网上公开吗解决方案三:引用1楼andywangguanxi的回复: 你的充值售电软件会网上公开吗 不在网上公开,但是,如果我们当地的同行业竞争对手搞到我们的软件(那是很容易的),而后反编译,那就可以仿造我们的产品,以低价争抢我们原有的客户资源,那是很危险的.解决方案四

在ASP.NET中上传图片并生成缩略图的C#源码

asp.net|上传|上传图片|缩略图 在ASP.NET中上传图片并生成缩略图的C#源码 using System;   using System.Collections;   using System.ComponentModel;   using System.Data;   using System.Drawing;   using System.Web;   using System.Web.SessionState;   using System.Web.UI;   using Sys