nginx-0.8.38源码探秘(一)

来源:互联网 发布:unity3d好找工作吗 编辑:程序博客网 时间:2024/05/16 10:35

本文档的Copyleft归L.L所有,使用GPL发布,可以自由转载,转载时请务必以超链接形式标明文章原始出处,严禁用于任何商业用途。

email: cc.dd.14@163.com
来源: http://blog.csdn.net/ccdd14

 

 

先推荐几个研究nginx源码的好网址:

http://blog.csdn.net/kenbinzhang/category/603177.aspx;

 

http://code.google.com/p/nginxsrp/wiki/NginxCodeReview;

 

http://hi.baidu.com/langwan/blog/category/%D4%B4%C2%EB%B7%D6%CE%F6。

 

 

网上分析nginx源码的文章很多,但感觉分析的不够具体和完整,而且都是比较老的nginx版本。本源码分析基于nginx-0.8.38版本,力求做到更具体和更完整,这是一种自我学习,希望和对此有兴趣的朋友一起探讨,有不正确的地方,也请各位指正。

 

那么一切从main开始吧!

 

ngx_get_options函数是main调用的第一个函数,比较简单,它负责分析命令行参数,将相应的值赋给对应的全局变量,其中:

1. ngx_prefix表示nginx的路径前缀,默认为/usr/local/nginx;

2. ngx_conf_file表示nginx配置文件的路径,默认为/usr/local/nginx/conf/nginx.conf;

3. ngx_test_config表示是否开启测试配置文件,如配置文件的语法是否正确,配置文件是否可正确打开。

 

ngx_time_init函数格式化nginx的日志时间,包括ngx_cached_err_log_time,ngx_cached_http_time,ngx_cached_http_log_time,ngx_cached_time。主要操作在ngx_time_update内,先获取系统当前时间,与之前保存的时间比较(注意slot),如果已经过时,则将时间重新更新,ngx_cached_time总是指向当前时间的cached_time。最后还使用了内存屏障ngx_memory_barrier,确保读写顺序。

 

ngx_log_init函数初始日志结构,主要是对ngx_log变量操作。初始log级别为NGX_LOG_NOTICE。接着分析error_log日志路径,获得完整的日志路径(默认为:/usr/local/nginx/logs/error.log)后,打开日志,获取对应的fd。

 

接下来碰到了ngx_cycle,这是一个非常重要的变量,初始指向init_cycle,然后创建了1024大小的内存池,在后面将会使用到。

 

ngx_save_argv函数将命令行参数浅拷贝一份到ngx_os_argv,深拷贝一份到ngx_argv(为什么要复制两份?)。并将环境变量浅拷贝一份到ngx_os_environ。

 

ngx_process_options获取配置文件nginx.conf的绝对路径。默认下,ngx_cycle的如下成员分别为:

1. conf_prefix =/usr/local/nginx/conf;

2. prefix = /usr/local/nginx/;

3. conf_file = /usr/local/nginx/conf/nginx.conf。

 

ngx_os_init函数获取OS名称和版本号,CPU个数,单个进程能打开的最大文件数,修改ps命令显示的nginx进程名称。获取OS信息

是通过ngx_os_specific_init实现的,其内调用了uname,最重要的语句是ngx_os_io = ngx_linux_io,看看这个结构的组成:

 

更改了ngx_os_io 的默认配置,注册了linux系统的钩子函数,唯一不同的是ngx_linux_sendfile_chain,里面用系统函数sendfile实

现两个文件之间的数据传输,它直接在内核空间拷贝数据,非常高效。ngx_init_setproctitle实现更改进程名称,因为argv[]和environ[]

是相续存储,先遍历完argv,这时ngx_os_argv_last=environ[0],并将environ保存在新分配的内存p中,最后

ngx_os_argv_last=argv[0],此函数之前有详细注解,请仔细理解。ngx_cpuinfo函数获取cpu信息,主要是得到缓存行大小,保存在

ngx_cacheline_size中,也可以通过/proc/cpuinfo获取。在linux中,ngx_inherited_nonblocking=0。另外,ngx_ncpu最多为1?


ngx_add_inherited_sockets函数打开上次保存在环境变量NGINX里的socket,linux一般不设置这个变量,直接返回。

 

接着遇到了ngx_modules变量,这是nginx模块化思想的实现核心。每个模块都会注册自己需要的钩子函数。

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

}

以上代码主要是对每个模块建立索引,ngx_max_module保存总的模块数。

 

ngx_init_cycle函数是个庞然大物,嗯......那就把它留到下章讲解了。

 

可以看到,nginx大量使用全局变量,这是一个令人头疼的问题!

原创粉丝点击