nginx0.1.0之event模块初始化源码分析(3)

2024-03-27 21:48

本文主要是介绍nginx0.1.0之event模块初始化源码分析(3),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前面已经分析了event初始化的整体流程和第一步create_conf,接下来看一下第二步ngx_conf_parse。这里不分析该函数的代码,该函数主要是遍历配置文件的内容,然后读取命令和参数。最后匹配nginx所有模块的配置,找到处理该指令的函数。我们首先看一下event模块中ngx_event_core_module模块的指令配置。

static ngx_command_t  ngx_event_core_commands[] = {{ ngx_string("connections"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_event_connections,0,0,NULL },{ ngx_string("use"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_event_use,0,0,NULL },{ ngx_string("multi_accept"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_conf_set_flag_slot,0,offsetof(ngx_event_conf_t, multi_accept),NULL },{ ngx_string("accept_mutex"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_conf_set_flag_slot,0,offsetof(ngx_event_conf_t, accept_mutex),&ngx_accept_mutex_post },{ ngx_string("accept_mutex_delay"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_conf_set_msec_slot,0,offsetof(ngx_event_conf_t, accept_mutex_delay),NULL },{ ngx_string("debug_connection"),NGX_EVENT_CONF|NGX_CONF_TAKE1,ngx_event_debug_connection,0,0,NULL },ngx_null_command
}

然后在看一下每个指令处理函数的代码。

connections指令

//把连接数记录在结构体中
static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,void *conf)
{ngx_event_conf_t  *ecf = conf;ngx_str_t  *value;// 已经初始化过了if (ecf->connections != NGX_CONF_UNSET_UINT) {return "is duplicate" ;}// 从配置文件中解析出来的配置value = cf->args->elts;// 字符串转成整形ecf->connections = ngx_atoi(value[1].data, value[1].len);if (ecf->connections == (ngx_uint_t) NGX_ERROR) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid number \"%s\"", value[1].data);return NGX_CONF_ERROR;}cf->cycle->connection_n = ecf->connections;return NGX_CONF_OK;
}

use指令

// 记录use和name的值
static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ngx_event_conf_t  *ecf = conf;ngx_int_t             m;ngx_str_t            *value;ngx_event_conf_t     *old_ecf;ngx_event_module_t   *module;if (ecf->use != NGX_CONF_UNSET_UINT) {return "is duplicate" ;}value = cf->args->elts;if (cf->cycle->old_cycle->conf_ctx) {old_ecf = ngx_event_get_conf(cf->cycle->old_cycle->conf_ctx,ngx_event_core_module);} else {old_ecf = NULL;}// 判断使用哪个事件驱动模块,比如use epoll,则使用epollfor (m = 0; ngx_modules[m]; m++) {if (ngx_modules[m]->type != NGX_EVENT_MODULE) {continue;}module = ngx_modules[m]->ctx;if (module->name->len == value[1].len) {if (ngx_strcmp(module->name->data, value[1].data) == 0) {// 存储事件模块的下标,而不是字符串ecf->use = ngx_modules[m]->ctx_index;ecf->name = module->name->data;if (ngx_process == NGX_PROCESS_SINGLE&& old_ecf&& old_ecf->use != ecf->use){ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"when the server runs without a master process ""the \"%s\" event type must be the same as ""in previous configuration - \"%s\" ""and it can not be changed on the fly, ""to change it you need to stop server ""and start it again",value[1].data, old_ecf->name);return NGX_CONF_ERROR;}return NGX_CONF_OK;}}}ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid event type \"%s\"", value[1].data);return NGX_CONF_ERROR;
}

multi_accept指令

char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{char  *p = conf;ngx_str_t        *value;ngx_flag_t       *fp;ngx_conf_post_t  *post;fp = (ngx_flag_t *) (p + cmd->offset);if (*fp != NGX_CONF_UNSET) {return "is duplicate";}value = cf->args->elts;// on代表开启if (ngx_strcasecmp(value[1].data, "on") == 0) {*fp = 1;} else if (ngx_strcasecmp(value[1].data, "off") == 0) {*fp = 0;} else {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"invalid value \"%s\" in \"%s\" directive, ""it must be \"on\" or \"off\"",value[1].data, cmd->name.data);return NGX_CONF_ERROR;}// 设置完值后执行后置函数,一般是参数检查if (cmd->post) {post = cmd->post;return post->post_handler(cf, post, fp);}return NGX_CONF_OK;
}

accept_mutex指令(见上面的ngx_conf_set_flag_slot函数)

该指令配置了handle函数
ngx_conf_post_t  ngx_accept_mutex_post = { ngx_accept_mutex_check } 
static char *ngx_accept_mutex_check(ngx_conf_t *cf, void *post, void *data)
{
// 不支持该功能,重置字段
#if !(NGX_HAVE_ATOMIC_OPS)ngx_flag_t *fp = data;*fp = 0;ngx_conf_log_error(NGX_LOG_WARN, cf, 0,"\"accept_mutex\" is not supported, ignored");#endifreturn NGX_CONF_OK;
}

accept_mutex_delay指令

char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{char  *p = conf;ngx_msec_t       *msp;ngx_str_t        *value;ngx_conf_post_t  *post;msp = (ngx_msec_t *) (p + cmd->offset);if (*msp != NGX_CONF_UNSET_MSEC) {return "is duplicate";}value = cf->args->elts;// 把字符串解析成时间*msp = ngx_parse_time(&value[1], 0);if (*msp == (ngx_msec_t) NGX_ERROR) {return "invalid value";}if (*msp == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {return "value must be less than 597 hours";}if (cmd->post) {post = cmd->post;return post->post_handler(cf, post, msp);}return NGX_CONF_OK;
}

debug_connection指令

static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,void *conf)
{
// 配置后需要开启debug参数
#if (NGX_DEBUG)ngx_event_conf_t  *ecf = conf;in_addr_t       *addr;ngx_str_t       *value;struct hostent  *h;value = cf->args->elts;/* AF_INET only */if (!(addr = ngx_push_array(&ecf->debug_connection))) {return NGX_CONF_ERROR;}// 将ip转成长整型*addr = inet_addr((char *) value[1].data);// 转成功则返回if (*addr != INADDR_NONE) {return NGX_OK;}// 没转成功可能是一个主机字符串,获取该主机对应的ip信息h = gethostbyname((char *) value[1].data);if (h == NULL || h->h_addr_list[0] == NULL) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"host %s not found", value[1].data);return NGX_CONF_ERROR;
}*addr = *(in_addr_t *)(h->h_addr_list[0]);#elsengx_conf_log_error(NGX_LOG_WARN, cf, 0,"\"debug_connection\" is ignored, you need to rebuild ""nginx using --with-debug option to enable it");#endifreturn NGX_OK;
}

还有事件驱动模块的一些配置,比如epoll模块的epoll_events指令,几乎都是简单地对相应模块的配置结构体的某个字段进行赋值。

到这里,event模块关于配置文件解析的部分就结束了。主要就是对下图中最右边的那个数组里的结构体进行赋值。在这里插入图片描述

这篇关于nginx0.1.0之event模块初始化源码分析(3)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853493

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛