"源码之下,了无秘密"。这篇文章是nginx源码分享系列的首篇,希望和大家分享阅读过程中的知识和心得。在看源码的过程中,有以下两个点阅读技巧,尤其是阅读比较大的项目很有用。
一方面可以带着问题去阅读,可以对抗学习上的枯燥。比如,未读源码前看到资料中nginx的一主多从进程模型图,可以提前想想自己如何实现,难点是什么。比如,fork的时机是什么?daemon主进程如何与子进程高效沟通?如何实现热更新?
另一方面可先从细节中汲取小养分,提升学习成就感。比如看某些内存池的代码,本身代码量很大;但里面用到的4字节取整、地址判断是否2的倍数等逻辑都是不超过20行的代码,完全可以记录下这些小收获,毕竟刷leetcode也能用到是吧?
所以,这个系列笔者不愿简单重复现有nginx书中所有章节,而是面向功能讲解实现,面向实现寻找技巧,以求点面结合。
nginx的源码结构如下图所示,其中脚本文件在auto目录中,编译的时候运行configure脚本即可;整个编译的过程都在这个脚本里面。
nginx源码项目结构
其中configure文件用于生成后期编译遇到的MakeFile文件,这个脚本调用auto目录下的脚本顺序如下图所示;可以借此理清整个编译依赖的关系以及nginx源码的组成。
configure中调用脚本生成MakeFile流程
这里主要分析下auto/modules这个文件,nginx的代码由许多模块构成,既包括自身模块,如:core、http、mail等;也包含第三方的模块,如ngx_rtmp_live_module 、nginx_upstream_check_module-master等。当我们去开发一个nginx模块,就需要按照其编译脚本的格式写对应的脚本。
# 省略.....
if [ $USE_OPENSSL = YES ]; then
ngx_module_type=CORE
ngx_module_name=ngx_openssl_module
ngx_module_incs=
ngx_module_deps=src/event/ngx_event_openssl.h
ngx_module_srcs="src/event/ngx_event_openssl.c
src/event/ngx_event_openssl_stapling.c"
ngx_module_libs=
ngx_module_link=YES
ngx_module_order=
. auto/module
fi
# 省略.....
if [ $STREAM_SPLIT_CLIENTS = YES ]; then
ngx_module_name=ngx_stream_split_clients_module
ngx_module_deps=
ngx_module_srcs=src/stream/ngx_stream_split_clients_module.c
ngx_module_libs=
ngx_module_link=$STREAM_SPLIT_CLIENTS
. auto/module
fi
if [ $STREAM_GEO = YES ]; then
ngx_module_name=ngx_stream_geo_module
ngx_module_deps=
ngx_module_srcs=src/stream/ngx_stream_geo_module.c
ngx_module_libs=
ngx_module_link=$STREAM_GEO
. auto/module
fi
# 省略.....
上面片段的是auto/modules中nginx编译自身模块的例子。可以看到,一个nginx模块想要融入编译,需要设置一些变量,包括ngx_module_type、ngx_module_name、ngx_module_deps、ngx_module_srcs等。这些变量不用死记,只需要在开发的时候到auto/modules中跟踪下即可知道具体意义。
那么nginx是如何查找第三方模块呢?在auto/modules的尾部,可以看到如下:
if test -n "$NGX_ADDONS"; then
echo configuring additional modules
for ngx_addon_dir in $NGX_ADDONS
do
echo "adding module in $ngx_addon_dir"
ngx_module_type=
ngx_module_name=
ngx_module_incs=
ngx_module_deps=
ngx_module_srcs=
ngx_module_libs=
ngx_module_order=
ngx_module_link=ADDON
if test -f $ngx_addon_dir/config; then
. $ngx_addon_dir/config
echo " + $ngx_addon_name was configured"
else
echo "$0: error: no $ngx_addon_dir/config was found"
exit 1
fi
done
fi
在上图中可以看到,nginx会记录编译时记录类似--add-module=./src/dev_http/hello 的选项,遍历这些第三方目录中的config脚本,config脚本中包含上小节中类似的片段,如
# ./coonfigure --add-module=./src/dev_http/hello
ngx_addon_name=ngx_http_ndg_hello_module
ngx_module_name=ngx_http_ndg_hello_module
ngx_module_type=HTTP
ngx_module_srcs="$ngx_addon_dir/ngx_http_ndg_hello_module.c"
. auto/module
以上就是第三方模块融入nginx中的方式~当我们开发模块的时候,也可以借鉴成熟的ngx开源的模块,模仿其中的config文件去开发。
回顾下,这一篇主要讲解了nginx编译脚本configure的执行流程,它用来生成最终编译的MakeFile文件。这里有两个小问题:
(1)在笔者当前工作中使用的脚本,基本都是固定参数的。nginx 的configure脚本的参数却是不确定,如何能方便迭代取出这些参数?
(2)在脚本嵌套调用的过程中,如何能父脚本得到子脚本中变量的值?即bash的作用域或者说上下文机制是怎么样的?
在下一篇中,让我们解答下以上两个问题~
留言与评论(共有 0 条评论) “” |