1.Nginx源码导读:[3]Ngnix头文件处理
2.Nginx源码分析 - 基础数据结构篇 - 数组结构 ngx_array.c
3.Nginx源码分析 - 主流程篇 - Nginx的码书启动流程
4.Nginx源码分析 - Event事件篇 - Event模块和配置的初始化
5.Nginx源码分析—HTTP模块之TCP连接建立过程详解
6.Nginx源码分析 - 主流程篇 - 全局变量cycle初始化
Nginx源码导读:[3]Ngnix头文件处理
这节主要讲一下nginx , 对头文件的码书包含 ,怎么处理多次包含的码书 ,其实也可以是码书小的C语言知识点
在nginx中有很多头文件 ngx_core.h ngx_errno.h 等等, 并且他们很多相互包含了 ,码书大家可能会想那不是码书采集 资源源码有重复定义了很多数据结构吗 ?
回答是当然不是,还记得上一节中的码书头文件吗 ,在这我们也拿过来 ,码书 ngx_config.h : #ifndef _NGX_CONFIG_H_INCLUDED_ #define _NGX_CONFIG_H_INCLUDED_ #include "ngx_linux_config.h" typedef intptr_t ngx_int_t; typedef uintptr_t ngx_uint_t; typedef intptr_t ngx_flag_t; #endif 发现了吗 ,码书 nginx开头都有 #ifndef XXXXX ,码书nginx就是用这个条件宏来去重的 ,如果第一次就会#define_NGX_CONFIG_H_INCLUDED_ ,码书以后某个文件在include这个头文件 ,#ifndef _NGX_CONFIG_H_INCLUDED_ 这个判断就是码书false了,直接就都#endif了
#ifndef这个语法是码书预处理执行的 ,类似于方面里面的码书if语句 ,但是码书预处理不同的是 ,处理完了 ,不满足条件的 ,编译后是不存的 , 而if语句是会怎么的 ,是在运行时做的条件判断
Nginx源码分析 - 基础数据结构篇 - 数组结构 ngx_array.c
Nginx的Array结构小巧,主要用于存储小块内存。每个元素大小固定,基于Nginx的pool实现数据结构。
数组基础数据结构定义如下:
1. elts:指向数组第一个元素的指针
2. nelts:未使用元素计数器
3. size:每个元素大小,固定
4. nalloc:已分配元素总数。当元素不足时,Nginx自动扩容
5. pool:数组和元素所需内存分配在pool内存池上
数组实现包括:
1. ngx_array_create:创建数组,定义元素数量和大小
2. ngx_array_destroy:销毁数组,检查元素是否在内存池结尾,回收内存
3. ngx_array_push:获取单个元素
4. ngx_array_push_n:获取多个元素
Nginx的Array结构设计简洁,高效管理小块内存,提供灵活的创建、销毁、分支结构的源码元素获取功能。
Nginx源码分析 - 主流程篇 - Nginx的启动流程
深入解析Nginx的核心,理解基础数据结构对源码解读至关重要。主流程的精髓隐藏在nginx.c的main()函数中,它启动的每一个步骤都如同乐谱上的一段旋律,优雅而有序。启动乐章
首先,指挥棒落在ngx_get_options上,它如同乐团指挥,优雅地解析启动命令行参数。接着,ngx_time_init、ngx_getpid和ngx_log_init依次登场,为时间、进程标识和日志设置调音。它们共同完成了一次细致入微的初始化过程,为接下来的演出铺平道路。 紧接着,ngx_init_cycle指挥全局变量的诞生,包括一致性哈希表的初始化,以及处理系统变量的微妙操作。随后,它引导我们进入一个关键环节:继承socket,初始化模块,设置信号处理,配置文件的获取和pid文件的创建,如同交响乐中的序曲,为后续的进程管理做准备。乐章高潮
当进入ngx_master_process_cycle部分,主进程的魔法开始显现。它如魔术师般,通过创建子进程,开课吧源码阅读让各个模块和事件监听开始各自的旋律。在这里,每个参数处理都如同精心编排的音符,确保演奏的和谐。关键步骤
在ngx_get_options中,启动命令参数如-s stop/start/restart的解读,是理解Nginx行为的关键。而在幕后,ngx_save_argv负责存储这些参数,ngx_process_options则如同指挥家,将参数的魔力注入到ngx_cycle的结构中。 特别关注的全局变量,如ngx_show_help、ngx_conf_file,它们是Nginx运行的调色板。ngx_save_argv和ngx_process_options如同调色师,精心调配每个参数的色彩。模块初始化的序曲
ngx_preinit_modules是模块世界的序曲,它负责初始化配置路径、处理参数,以及配置文件的定位。在这里,每个动作都精确而有序,确保每个模块都能在正确的时间奏响属于自己的旋律。 在ngx_module.c中,模块编号的分配和配置文件的处理,如同管弦乐队的编排,确保每个乐器都能和谐共奏。而创建PID文件的函数ngx_create_pidfile则如定音锤,为整个系统敲定最后的音符。 每个重要模块,如ngx_add_inherited_sockets、黑马主力指标源码ngx_init_cycle、ngx_signal_process和ngx_master_process_cycle,都在各自的角色中发挥着不可或缺的作用,共同编织出Nginx启动的华美乐章。Nginx源码分析 - Event事件篇 - Event模块和配置的初始化
深入探讨Nginx源码分析中的Event事件篇,专注于Event模块和配置的初始化,旨在清晰理解配置解析与模块初始化的协同工作。
Event模块的配置解析分为两层:最外层的events模块以及内层的ngx_events_module事件模块和ngx_event_core_module事件核心模块。
在初始化流程中,最开始配置文件的初始化调用的是核心模块的指令集,即events模块的配置解析指令函数:ngx_events_block。这里涉及的事件模块结构主要包括:事件模块本身和事件核心模块,每层模块拥有特定的角色与功能。
具体而言,事件核心模块初始化函数为ngx_event_module_init,而配置解析流程则始于解析顶层“event”的配置,并通过ngx_conf_parse方法实现。在顶层配置解析完成后,将进入对事件块block中的内容解析,即ngx_events_block方法执行,此方法为事件命令集的回调函数,负责核心模块配置信息的创建。
配置初始化中,首先在ngx_init_cycle方法中完成核心模块初始化,但由于ngx_events_module中的create_conf方法为NULL,故不会调用创建配置的步骤。接着,顶层配置解析完成后,进入事件块block内容解析,通过遍历模块命令集cmd->set方法,完成具体配置的创建与初始化。
在配置获取过程中,hbase源码是什么首先从ngx_events_module获取配置信息,再通过查找找到ngx_event_core_module的配置信息。配置的获取涉及从事件模块到事件核心模块的层级访问,确保配置信息的准确获取。
综上所述,Event事件篇中的模块和配置初始化通过多层解析与调用,确保了Nginx配置的完整执行与模块功能的有效实现。这一过程不仅涉及配置的层次结构,还涉及到初始化函数的精确调用与配置解析的细致处理,体现了Nginx源码设计的严谨与高效。
Nginx源码分析—HTTP模块之TCP连接建立过程详解
Nginx源码中HTTP模块的TCP连接建立过程详细解析如下:
首先,监听套接字的初始化由ngx_http_optimize_servers函数负责,这个函数在HTTP模块的初始化过程中起关键作用,通过ngx_http_init_listening和ngx_http_add_listening函数创建并设置监听套接字,根据服务器配置的每个IP地址和端口进行。
在main函数的ngx_init_cycle()中,通过ngx_open_listening_sockets调用了一系列设置,包括非阻塞模式、缓冲区大小、绑定和监听等。HTTP模块的优先级高于Event模块,HTTP模块初始化后,会调用ngx_http_init_connection,为每个客户端连接设置初始化处理函数。
Event模块的初始化则通过ngx_event_process_init函数,每个worker进程都会调用它,设置接收连接的回调函数为ngx_event_accept。当客户端连接时,Nginx会进入事件循环,检测到读事件会调用ngx_event_accept,进一步处理连接请求。
调用ngx_event_accept后,会创建ngx_connection_t结构,并将最初的读取事件回调改为ngx_http_wait_request_handler,后续的客户端读取事件都将通过这个函数处理。这意味着ngx_http_wait_request_handler成为了HTTP模块数据处理的入口点。
整个连接过程可以用以下流程图概括:
1. 初始化监听套接字
2. 设置套接字选项和回调函数
3. 客户端连接时,调用ngx_event_accept
4. ngx_http_init_connection处理连接并修改回调
5. 客户端读取事件通过ngx_http_wait_request_handler处理
以上是Nginx连接建立过程的核心步骤。
Nginx源码分析 - 主流程篇 - 全局变量cycle初始化
Nginx的全局初始化过程围绕全局变量“cycle”展开,位于/src/core/cycle.c文件,其数据结构为“ngx_cycle_t”。了解Nginx源码前应掌握cycle全局变量初始化流程。 cycle初始化分为以下步骤: 创建内存池 用于后续分配的所有内存。 拷贝配置文件路径前缀 如“/usr/local/nginx”,存储在cycle->conf_prefix中。 复制Nginx路径前缀 存储于cycle->prefix。 复制配置文件信息 包含文件路径,如“/nginx/conf/nginx.conf”。 复制配置参数信息 初始化路径信息 初始化打开的文件句柄 初始化shared_memory链表 新旧链表比较,保留相同内存,释放不同。 遍历并打开文件列表(如日志、配置文件) 创建并初始化共享内存 比较新旧共享内存,保留或创建。 处理listening数组并开始监听 处理socket监听。 关闭或删除old_cycle资源 关键点在于内存池的创建、配置文件解析、文件句柄与共享内存的初始化、socket监听与资源关闭,整个流程确保Nginx核心组件的初始化完成。nginx源码分析--master和worker进程模型
一、Nginx整体架构
正常执行中的nginx会有多个进程,其中最基本的是master process(主进程)和worker process(工作进程),还可能包括cache相关进程。
二、核心进程模型
启动nginx的主进程将充当监控进程,主进程通过fork()产生的子进程则充当工作进程。
Nginx也支持单进程模型,此时主进程即是工作进程,不包含监控进程。
核心进程模型框图如下:
master进程
监控进程作为整个进程组与用户的交互接口,负责监护进程,不处理网络事件,不负责业务执行,仅通过管理worker进程实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
master进程通过sigsuspend()函数调用大部分时间处于挂起状态,直到接收到信号。
master进程通过检查7个标志位来决定ngx_master_process_cycle方法的运行:
sig_atomic_t ngx_reap;
sig_atomic_t ngx_terminate;
sig_atomic_t ngx_quit;
sig_atomic_t ngx_reconfigure;
sig_atomic_t ngx_reopen;
sig_atomic_t ngx_change_binary;
sig_atomic_t ngx_noaccept;
进程中接收到的信号对Nginx框架的意义:
还有一个标志位:ngx_restart,仅在master工作流程中作为标志位使用,与信号无关。
核心代码(ngx_process_cycle.c):
ngx_start_worker_processes函数:
worker进程
worker进程主要负责具体任务逻辑,主要关注与客户端或后端真实服务器之间的数据可读/可写等I/O交互事件,因此工作进程的阻塞点在select()、epoll_wait()等I/O多路复用函数调用处,等待数据可读/写事件。也可能被新收到的进程信号中断。
master进程如何通知worker进程进行某些工作?采用的是信号。
当收到信号时,信号处理函数ngx_signal_handler()会执行。
对于worker进程的工作方法ngx_worker_process_cycle,它主要关注4个全局标志位:
sig_atomic_t ngx_terminate;//强制关闭进程
sig_atomic_t ngx_quit;//优雅地关闭进程(有唯一一段代码会设置它,就是接受到QUIT信号。ngx_quit只有在首次设置为1时,才会将ngx_exiting置为1)
ngx_uint_t ngx_exiting;//退出进程标志位
sig_atomic_t ngx_reopen;//重新打开所有文件
其中ngx_terminate、ngx_quit、ngx_reopen都将由ngx_signal_handler根据接收到的信号来设置。ngx_exiting标志位仅由ngx_worker_cycle方法在退出时作为标志位使用。
核心代码(ngx_process_cycle.c):
Nginx源码阅读(五):启动前的准备
在 Nginx 启动前,一系列初始化流程和变量设定至关重要。这些准备工作确保 Nginx 正常运行,高效管理资源并优化性能。接下来,我们将分步骤详细介绍 Nginx 启动前的准备过程。1. ngx_os_init 获取系统级资源
ngx_os_init 负责初始化操作系统级资源,将关键参数赋值给全局变量。这些参数包括页面大小、缓存行大小、最大套接字数等。 系统级参数获取依赖于 sysconf 函数,它用于查询系统特定参数,如 CPU 核心数量、内存大小、进程打开的最大文件数等。 _SC_NPROCESSORS_CONF返回 CPU 核心数量,包括不可用核心。
_SC_NPROCESSORS_ONLN返回系统中可用的 CPU 核心数量。
_SC_PAGESIZE表示系统页面大小(字节单位)。
_SC_PHYS_PAGES表示系统物理内存页数。
_SC_OPEN_MAX表示进程可以打开的最大文件数。
_SC_GETPW_R_SIZE_MAX表示 getpwuid_r 函数使用的缓冲区大小限制。
另一个关键函数 ngx_cpuinfo 用于获取 CPU 的 L2 缓存行大小。理解 CPU 缓存级别有助于优化 Nginx 性能。L1 缓存位于 CPU 核心内,是最快的缓存层。
L2 缓存在 CPU 芯片上,但比 L1 缓存距离核心更远。
L3 缓存位于 CPU 外部,速度仅次于内存,但大小较大。
不同 CPU 的缓存大小差异显著,如图所示。L1 和 L2 缓存通常在 CPU 核之间不共享,而 L3 缓存为所有核心共享。 此外,getrlimit 和 setrlimit 函数用于查询和更改进程资源限制。rlimit 结构体参数用于指定资源限制,如最大句柄数,即最大可创建的套接字数量。2. ngx_crc_table_init 初始化 CRC 表
此函数初始化循环冗余校验(CRC)表,确保计算效率。通过将指向校验表格的指针ngx_crc_table_short 对齐至缓存行大小,提高性能。 CRC 是一种用于检测数据传输或保存错误的校验方法。生成的数字附加至数据后,接收端进行验证以确保数据未变。具体原理可参考网络资料。3. ngx_add_inherited_sockets 继承套接字
在平滑升级场景下,ngx_add_inherited_sockets 用于继承原有监听套接字。通过环境变量 NGINX 获取套接字信息,将其加入 init_cycle 的 listening 数组。完成继承后,设置全局变量 ngx_inherited 为 1。 此函数仅在平滑升级过程中使用,通常情况下无需执行。因此,我们不对该函数进行过多讨论。Nginx源码分析 - HTTP模块篇 - TCP连接建立过程
Nginx源码分析 - HTTP模块篇 - TCP连接建立过程
在上一章节中,我们已经了解了HTTP模块的初始化过程。本章节将深入剖析监听套接字的初始化函数以及Nginx连接的全程流程。 首先, ngx_http_optimize_servers 是关键函数,它负责Nginx服务监听套接字的优化配置。这个函数在Nginx启动时,会初始化并优化服务器的侦听策略。 紧接着, ngx_http_init_listening 和 ngx_http_add_listening 函数共同作用,创建和设置监听套接字(listening),为后续的网络连接做好准备。 理解了Event模块的进程初始化后,结合 ngx_http_optimize_servers 的工作,我们可以构建出Nginx连接的完整流程图。这个流程涉及服务器的监听,客户端的请求,以及两者之间的TCP连接建立。 让我们通过下面的流程概述来直观地理解:服务器通过 ngx_http_optimize_servers 函数设置监听套接字,等待客户端连接请求。
当客户端发起连接时,Nginx通过 ngx_http_add_listening 创建新的TCP连接。
通过Event模块的事件驱动,Nginx接收并处理客户端的HTTP请求,开始HTTP会话。