设为首页 收藏本站
查看: 742|回复: 0

[经验分享] Nginx源码分析-启动初始化过程(一)

[复制链接]

尚未签到

发表于 2015-7-26 13:45:11 | 显示全部楼层 |阅读模式
  Nginx的启动初始化在src/core/nginx.c的main函数中完成,当然main函数是整个Nginx的入口,除了完成启动初始化任务以外,也必定是所有功能模块的入口之处。Nginx的初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。下面具体看一下main函数为Nginx的启动过程做了哪些初始化方面的事情。
  main函数做的第一件事情就是对参数选项进行处理,和普通的Linux程序如出一辙,如下:


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


  • ngx_time_init();  
  • (NGX_PCRE)  
  • ngx_regex_init();  
  • if  
  • ngx_pid = ngx_getpid();  
  • log = ngx_log_init(ngx_prefix);  
  • if (log == NULL) {  
  •     return 1;  
  • }  
      ngx_time_init();#if (NGX_PCRE)ngx_regex_init();#endifngx_pid = ngx_getpid();log = ngx_log_init(ngx_prefix);if (log == NULL) {return 1;}
  上述几行代码的功能如其名,time和log后面再用单独的文字来分析,此处就不多说了。
  


  • if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK){  
  •     return 1;  
  • }  
      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) {  

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


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


  • if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {  
  •     return 1;  
  • }  
      if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {return 1;}
  通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。  
  


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


  • 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_openssl_module,  
  •     &ngx_http_module,  
  •     。。。  
  • };  


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


  • if (ngx_init_signals(cycle->log) != NGX_OK) {  
  •     return 1;  
  • }  
      if (ngx_init_signals(cycle->log) != NGX_OK) {return 1;}
  注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。


  • if (!ngx_inherited && ccf->daemon) {  
  •     if (ngx_daemon(cycle->log) != NGX_OK) {  
  •         return 1;  
  •     }  
  •     ngx_daemonized = 1;  
  • }  
      if (!ngx_inherited && ccf->daemon) {if (ngx_daemon(cycle->log) != NGX_OK) {return 1;}ngx_daemonized = 1;}
  ngx_daemon肯定就是用来实现守护进程的函数了,此处就不多废话了,有需要写server程序的,可以直接copy这段代码实现守护进程。


  • if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {  
  •     return 1;  
  • }  
      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文件。


  • if (ngx_process == NGX_PROCESS_SINGLE) {
  •     ngx_single_process_cycle(cycle);  
  • } else {  
  •     ngx_master_process_cycle(cycle);  
  • }  
      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的常用模型。既然此处已不再是初始化工作,那么就留到后续分析吧。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-90834-1-1.html 上篇帖子: django 部署,gunicorn、virtualenv、nginx 下篇帖子: Nginx 禁止IP访问
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表