Nginx源码分析-启动初始化过程(一)

Nginx的启动初始化在src/core/nginx.c的main函数中完成,当然main函数是整个Nginx的入口,除了完成启动初始化任务以外,也必定是所有功能模块的入口之处。Nginx的初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。下面具体看一下main函数为Nginx的启动过程做了哪些初始化方面的事情。 


main函数做的第一件事情就是对参数选项进行处理,和普通的Linux程序如出一辙,如下:

  1. if (ngx_get_options(argc, argv) != NGX_OK) {  
  2.         return 1;  
  3.   }  

if (ngx_get_options(argc, argv) != NGX_OK) { return 1; }

 Nginx用此函数对参数选项进行解析,从而采取相应的动作,比如:显示版本、测试配置等功能。其实此函数实现的很简陋,远没有Linux提供的getopt()那么强悍,但却可以达到跨平台的目的。


  1. ngx_time_init();  
  2. (NGX_PCRE)  
  3. ngx_regex_init();  
  4. if  
  5. ngx_pid = ngx_getpid();  
  6. log = ngx_log_init(ngx_prefix);  
  7. if (log == NULL) {  
  8.     return 1;  
  9. }  

ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; }

  上述几行代码的功能如其名,time和log后面再用单独的文字来分析,此处就不多说了。 


  

  1. if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK){  
  2.     return 1;  
  3. }  

if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK){ return 1; }

 将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这应该算是一个备份存储,方便后面的初始化工作能够随时获取命令行参数。


if (ngx_os_init(log) != NGX_OK) {  
  1.     return 1;  
  2. }  

if (ngx_os_init(log) != NGX_OK) { return 1; }

 完成操作系统的一些信息获取,如内存页面大小、系统限制资源等信息;所有的这些资源都将会被保存在对应的全局变量中,因此后续访问将会很便利。


  1. if (ngx_crc32_table_init() != NGX_OK) {  
  2.     return 1;  
  3. }  

if (ngx_crc32_table_init() != NGX_OK) { return 1; }

 初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法。crc算法此处就不做分析,网上一堆一堆的相关资料,有兴趣的同学可以了解。


  1. if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {  
  2.     return 1;  
  3. }  

if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; }

 通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。  


 

  1. ngx_max_module = 0; 
  2. for (i = 0; ngx_modules[i]; i++) {  
  3.     ngx_modules[i]->index = ngx_max_module++;  
  4. }  

ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; }

 额!!!这个循环中的ngx_modules数组好像没见定义,难不成是火星来的?当然不是,如其名,这就是一个存储所有模块的信息,包括自己开发的模块都会放到这个数组中,而这个神秘的数组却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中。这个循环的目的是清晰可见的——对所有模块进行索引编号,方便以后访问;同时借助ngx_max_module对所有模块进行了一次点数,确定究竟有多少模块。而神秘数组ngx_modules的长相大概如下:

  1. ngx_module_t *ngx_modules[] = {  
  2.     &ngx_core_module,           
  3.     &ngx_errlog_module,  
  4.     &ngx_conf_module,  
  5.     &ngx_events_module,  
  6.     &ngx_event_core_module,  
  7.     &ngx_epoll_module,  
  8.     &ngx_openssl_module,  
  9.     &ngx_http_module,  
  10.     。。。  
  11. };    

  1. cycle = ngx_init_cycle(&init_cycle);  

cycle = ngx_init_cycle(&init_cycle);

 这里将会初始化很多的东东到全局变量cycle中,是Nginx启动初始化的核心之处。ngx_init_cycle函数的过程比较多,放下一篇blog中逐段分析。


  1. if (ngx_init_signals(cycle->log) != NGX_OK) {  
  2.     return 1;  
  3. }  

if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; }

 注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。


  1. if (!ngx_inherited && ccf->daemon) {  
  2.     if (ngx_daemon(cycle->log) != NGX_OK) {  
  3.         return 1;  
  4.     }  
  5.     ngx_daemonized = 1;  
  6. }  

if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; }

 ngx_daemon肯定就是用来实现守护进程的函数了,此处就不多废话了,有需要写server程序的,可以直接copy这段代码实现守护进程。


  1. if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {  
  2.     return 1;  
  3. }  

if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; }

 玩过Nginx的人都知道,Nginx启动后有一个记录进程id的文件,这个文件里面就一个pid。原来这个pid就是在这个地方记录下来的。查看ngx_create_pidfile函数可以看到这样的一行代码

if (ngx_process > NGX_PROCESS_MASTER) {
    return NGX_OK;
},这行代码就说明了,不是master进程时,就不创建这样的一个pid文件。


  1. if (ngx_process == NGX_PROCESS_SINGLE) {
  2.     ngx_single_process_cycle(cycle);  
  3. else {  
  4.     ngx_master_process_cycle(cycle);  
  5. }  

if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); }

 到此就基本完成Nginx的启动初始化过程了,即将开始进程相关的工作了,这里最重要的ngx_master_process_cycle这个过程,在这个过程里实现了master-worker模式的进程模型,也是生成环境下Nginx的常用模型。既然此处已不再是初始化工作,那么就留到后续分析吧。

 

转载于:https://www.cnblogs.com/li-hao/archive/2013/02/28/2937258.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548073.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot实现国际化

在哔哩哔哩一位up主视频中学到的! 国际化 原理 通过Properties文件配置,配置完后通过Thymeleaf中的#{} 来取代原来的静态资源。例如: spring:# 关闭模板引擎的缓存thymeleaf:cache: falsemessages:encoding: UTF-8## 配置国际化绑定的文…

前端开发1之Node.js以及npm开发环境搭建

关于现今的前端开发,由于微服务架构的普及,前端工程师必须承担更重要的任务。现在的后端工程师无需考虑JS、Ajax和json的解析遍历,或许只需要处理前端请求过来的各种带参请求(Get/Post/Patch等),目前许多前…

开源中国iOS客户端学习——(八)网络通信AFNetworking类库

AFNetworking是一个轻量级的iOS网络通信类库,继ASI类库不在更新之后开发者们有一套不错选择; AFNetworking类库和使用教程: https://github.com/AFNetworking/AFNetworking 如果想深入研究有官方文档介绍:http://afnetworking.github.com/AFNetworking/ …

OpenGL 入门第一课 视窗以及三角形

请查看课件教程 下面是我粗劣画的过程图 下面是课件中的过程图 下面是未使用索引缓冲对象&#xff08;EBO&#xff09;的 #define GLEW_STATIC // 这个一定要加不然报错 静态链接库 #include<iostream> #include<GL/glew.h> #include<GLFW/glfw3.h> usin…

玩玩短视频平台和网课平台开发1——腾讯云对象储存COS的初步配置

近一两年来&#xff0c;抖音、快手等以短视频为手段的社交工具红遍了大江南北&#xff0c;腾讯也推出了"微视"平台&#xff0c;希望分一杯羹&#xff1b;传统的直播平台如&#xff1a;斗鱼直播、虎牙直播就更不用说了&#xff0c;甚至涌现了许多主打"知识付费&q…

解决从其它搜索引擎不能直接访问百度页面的问题

由于最近baidu和360又开始互咬了&#xff0c;从其它搜索引擎搜索到百度的结果时又变不能直接访问了&#xff0c;会出现如下界面。 需要手动点击这个链接才能访问&#xff0c;让人非常不爽。因此我写了一个chrome扩展解决这个问题&#xff0c;原理很简单&#xff1a;当遇到这种需…

基于JAVA的校园电商物流云平台 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快递公司模块2.4 物流订单模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 商品表3.2.2 快递公司表3.2.3 物流订单表 四、系统展示五、核心代码5.1 查询商品5.2 查询快递公司5.3 查…

OpenGL Sharders(着色器) 入门

着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。 // 顶点着色器 #version 330 core // 0号栏位读取顶点坐标 layout (location 0) in vec3 aPos; //1号栏位读取颜色颜色 …

玩玩机器学习1——ubuntu16.04 64位安装TensorFlow GPU+python3+cuda8.0+cudnn8.0

如今的机器学习运算大多数都是利用gpu进行&#xff0c;包括很大大型游戏&#xff0c;比特币的开采&#xff0c;都离不开GPU的运算&#xff0c;GPU已成为大型运算能力的主要硬件。 大名鼎鼎的机器学习开源框架&#xff0c;如TensorFlow和Caffe&#xff0c;Caffe2都建议使用GPU作…

[linux]Ubuntu12.1下打开terminal的方式

有的人比较习惯使用terminal&#xff0c;喜欢简单的文本窗口&#xff0c;刚使用ubuntu可能还不习惯&#xff0c;这里给出几种打开terminal的方法&#xff1a;1 图形界面中图一就是那个左上角红色方框里的图标&#xff0c;点击后搜索terminal就好了。图二2 使用快捷键Ctrl Alt …

OpenGL 自定义着色器(Shaders)

自定义着色器类 声明 #pragma once#include<string>class Shaders { public:Shaders(const char* vertexPath, const char* fragmentPath);~Shaders();std::string vertexString;std::string fragmentString;const char* vertexSource;const char* fragmentSource;unsi…

微信开发之——Ubuntu Apache2的https域名配置

我的网站是腾讯云服务器的&#xff0c;根据官网的SSL证书安装配置指示&#xff1a;https://cloud.tencent.com/document/product/400/4143 下载腾讯颁发的SSL证书&#xff1a;有3个文件&#xff0c;分别是&#xff1a; 1_root_bundle.crt&#xff0c;2_www.域名.com.crt&…

《统一沟通-微软-技巧》-20-Lync 2010如何在我的联系人列表中添加非联盟联系人...

Blog:http://dynamic.blog.51cto.com MSN:LiuJinFengmsn.com QQ:316190099如果加:A&#xff0e; 内部Lync用户:输入-英文名输入-中文名输入-中文名/英文名中包括的部分字符B&#xff0e; 联盟Lync用户:输入:邮件地址C&#xff0e; 非 Lync用户:在Outlook新建联系人让Lync与Outl…

texture 纹理(贴图)

纹理 纹理是一个2D图片&#xff08;甚至也有1D和3D的纹理&#xff09;&#xff0c;它可以用来添加物体的细节。 这是两张照片叠加的效果 由下面两张叠加而成 源代码 shaders类在自定义着色器 中有完整的源代码。 下边我们使用stb_image.h来解析图片。 #define GLEW_STATI…

如何进行防SQL注入?

1、过滤掉一些常见的数据库操作关键字&#xff1a;select,insert,update,delete,and,*等 或者通过系统函数&#xff1a;addslashes(需要被过滤的内容)来进行过滤。 2、在PHP配置文件中 Register_globalsoff;设置为关闭状态 //作用将注册全局变量关闭。 比如&#xff1a;接收POS…

微信开发4——PHP实现PC扫码授权登陆获取用户信息

首先须要申请,必须企业,个体工商户,媒体等&#xff0c;微信开放平台申请地址 https://open.weixin.qq.com/&#xff0c;要交300多的费用才能开通 1&#xff0c;编写入口&#xff1a;微信开放平台的扫码登陆开放的接口可以自动生成PC扫码页面&#xff0c;你得到了官方通过审核的…

计算机组成原理和体系结构----软考(到处copy)

计算机组成原理和体系结构数据的表示n进制转十进制十进制转n进制 使用短除法二进制转八进制和十六进制原码、反码、补码以及移码浮点数运算计算机结构计算机体系结构分类 - FlynnCISC 和 RISC流水线流水线计算流水线时间计算流水线吞吐率计算流水线的加速比计算流水线的效率计算…

一个笔试题

题目&#xff1a;输入一个数N&#xff0c;计算1、2、3、...、N这N个数进行排列组合&#xff0c;使得这个数列任意两个相邻数之和为素数&#xff0c;求结果T&#xff0c;T为这样的数列的个数&#xff1b; private static final Map<Integer, Boolean> SUSHU new HashMap&…

Ubuntu16.04安装Hadoop+Spark+pyspark大数据python开发环境

一&#xff0c;安装jdk1.8.0.144 下载地址&#xff1a;www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html Ubuntu配置jdk运行环境 export HADOOP_HOME/usr/local/hadoop export CLASSPATH$($HADOOP_HOME/bin/hadoop classpath):$CLASSPA…

C# 分割字符串方法

单个字符分割 string s"abcdeabcdeabcde"; string[] sArrays.Split(c); foreach(string i in sArray) Console.WriteLine(i.ToString()); 输出下面的结果: ab deab deab de 多个字符分割 string s"abcdeabcdeabcde string[] sArray1s.Split(new char[3]{c,d,e})…