nginx源码轻松学|1.从编译脚本谈起(上)

开篇:源码阅读技巧

"源码之下,了无秘密"。这篇文章是nginx源码分享系列的首篇,希望和大家分享阅读过程中的知识和心得。在看源码的过程中,有以下两个点阅读技巧,尤其是阅读比较大的项目很有用。

一方面可以带着问题去阅读,可以对抗学习上的枯燥。比如,未读源码前看到资料中nginx的一主多从进程模型图,可以提前想想自己如何实现,难点是什么。比如,fork的时机是什么?daemon主进程如何与子进程高效沟通?如何实现热更新?

另一方面可先从细节中汲取小养分,提升学习成就感。比如看某些内存池的代码,本身代码量很大;但里面用到的4字节取整、地址判断是否2的倍数等逻辑都是不超过20行的代码,完全可以记录下这些小收获,毕竟刷leetcode也能用到是吧?

所以,这个系列笔者不愿简单重复现有nginx书中所有章节,而是面向功能讲解实现,面向实现寻找技巧,以求点面结合。

nginx编译脚本结构

nginx的源码结构如下图所示,其中脚本文件在auto目录中,编译的时候运行configure脚本即可;整个编译的过程都在这个脚本里面。

nginx源码轻松学|1.从编译脚本谈起(上)

nginx源码项目结构

其中configure文件用于生成后期编译遇到的MakeFile文件,这个脚本调用auto目录下的脚本顺序如下图所示;可以借此理清整个编译依赖的关系以及nginx源码的组成。

nginx源码轻松学|1.从编译脚本谈起(上)

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 条评论) “”
   
验证码:

相关文章

推荐文章