社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  NGINX

Nginx源码分析之--auto/types/typedef脚本

郑尔多斯 • 6 年前 • 502 次点击  
阅读 50

Nginx源码分析之--auto/types/typedef脚本

微信公众号:Nginx源码分析
关注可了解更多的Nginx知识。任何问题或建议,请公众号留言;
关注公众号,有趣有内涵的文章第一时间送达!

回顾

我们在上一篇文章中详细的分析了auto/types/sizeof脚本源码,本文我们继续分析auto/types目录下的脚本文件。我们首先回顾一下nginx中的大致辅助脚本图片,如下图:

nginx辅助脚本
nginx辅助脚本

本文讲述一下auto/types/typedef脚本,

auto/types/typedef脚本

Nginx的脚本名称以及变量名称都是非常的直截了当,我们完全可以见名知意,这是我们在写代码的时候要学习借鉴的地方。从这个脚本的名称中我们即可以看到,它的作用就是生成typedef声明的。

auto/types/sizeof脚本

参数

ngx_type:类型1
ngx_types:类型2

功能

判断ngx_typengx_types是否存在,根据判断条件生成相应的typedef语句。

示例

我们这次先看一下脚本使用的示例,从而全面了解一下这个脚本。
auto/unix脚本中,调用了auto/types/typedef脚本,如下:




    
ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef
复制代码
脚本内容
echo $ngx_n "checking for $ngx_type ...$ngx_c"

cat << END >> $NGX_AUTOCONF_ERR

----------------------------------------
checking for $ngx_type

END

ngx_found=no

for ngx_try in $ngx_type $ngx_types
do

    cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
$NGX_INCLUDE_INTTYPES_H

int main() {
    $ngx_try i = 0;
    return 0;
}

END

    ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
              -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"


    eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"

    if [ -x $NGX_AUTOTEST ]; then
        if [ $ngx_try = $ngx_type ]; then
            echo " found"
            ngx_found=yes
        else
            echo ", $ngx_try used"
            ngx_found=$ngx_try
        fi
    fi

    rm -f $NGX_AUTOTEST

    if [ $ngx_found = no ]; then
        echo $ngx_n $ngx_try not found$ngx_c"

        echo "----------"    >> $NGX_AUTOCONF_ERR
        cat $NGX_AUTOTEST.c  >> $NGX_AUTOCONF_ERR
        echo "----------"    >> $NGX_AUTOCONF_ERR
        echo $ngx_test       >> $NGX_AUTOCONF_ERR
        echo "----------"    >> $NGX_AUTOCONF_ERR

    else
        break
    fi
done

if [ $ngx_found = no ]; then
    echo
    echo "$0: error: can not define $ngx_type"

    exit 1
fi

if [ $ngx_found != yes ]; then
    echo "typedef $ngx_found  $ngx_type;"   >> $NGX_AUTO_CONFIG_H
fi
复制代码
脚本分析

我们按照示例的调用例子进行脚本分析。

1). 首先是向控制台输出信息
我们在前面的文章中分析过ngx_c变量,这里不再赘述。
sh echo $ngx_n "checking for $ngx_type ...$ngx_c"
我们在终端上可以看到如下内容:
sh checking for uint64_t ...

2).NGX_AUTOCONF_ERR中生成内容。

cat << END >> $NGX_AUTOCONF_ERR

----------------------------------------
checking for $ngx_type

END

END
复制代码

所以,实际上向NGX_AUTOCONF_ERR中写入的内容是:

checking for uint64_t
复制代码

从前面的文章到现在,我们可以看出来,Nginx的每一步都有完善的日志,这对于监控程序的执行流程以及分析错误原因是非常有帮助的。

3). 生成测试程序

ngx_found=no
复制代码

这里首先将ngx_found的内容赋值为no,这个变量在后面用来表示是否存在我们要检测的数据类型。

接着,auto/types/typedef脚本通过一个for循环遍历传进来的ngx_typengx_types,每次循环处理过程都是一样。我们分析一下这个for循环。
对于每次循环,都会根据当前遍历到的变量生成一份测试用的c源码,如下:

    cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
$NGX_INCLUDE_INTTYPES_H

int main() {
    $ngx_try i = 0;
    return 0;
}

END
复制代码

实际对于我们示例的情况,第一次循环生成的代码如下:

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <inttypes.h>

int main() {
    uint64_t i = 0;
    return 0;
}
复制代码

这个源文件真的是很简单,main函数中只有一行实际的代码。这行代码的作用很简单:如果uint64_i这个类型存在的话,那么这个源文件肯定能编译成功,并且最终生成可以执行的目标文件。我们可以通过检测最终的目标文件是否可以被执行来间接的判断uint64_t类型是否存在。

4). 编译上面生成的源文件

ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
              -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"


    eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
复制代码

上面的ngx_test就是一个编译语句,具体内容如下:

gcc     -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64    -o objs/autotest objs/autotest.c
复制代码

紧接着的eval语句会执行ngx_test的内容,也就是执行编译语句,生成可以执行文件objs/autotest

5). 执行可执行程序

if [ -x $NGX_AUTOTEST ]; then
        if [ $ngx_try  = $ngx_type ]; then
        # $ngx_type是传给for循环的第一个循环参数。所以如果能够执行到这里,则说明第一个参数$ngx_type代表的类型存在
            echo " found"
            ngx_found=yes
        else
        # 如果执行到这里,那么说明$ngx_type代表的变量类型不存在,但是$ngx_types代表的变量类型存在, 这个时候 ngx_found就会被赋值为$ngx_types类型
            echo ", $ngx_try used"
            ngx_found=$ngx_try
        fi
fi
复制代码

nginx判断如果第4步生成的目标文件是是可执行文件-x $NGX_AUTOTEST,那么执行该目标文件.
这段代码的详细分析我已经在代码里面进行了注释。

6).删除目标文件

rm -f $NGX_AUTOTEST
复制代码

Nginx会在运行完可执行文件之后就将该文件删除,所以实际上我们在Nginx的目录中是不能看到这些文件的,它们都是临时文件。

7).根据上面的执行结果进行错误输出

if [ $ngx_found = no ]; then
        echo $ngx_n $ngx_try not found$ngx_c"

        echo "----------"    >> $NGX_AUTOCONF_ERR
        cat $NGX_AUTOTEST.c  >> $NGX_AUTOCONF_ERR
        echo "----------"    >> $NGX_AUTOCONF_ERR
        echo $ngx_test       >> $NGX_AUTOCONF_ERR
        echo "----------"    >> $NGX_AUTOCONF_ERR

    else
    # 如果当前的数据类型存在,那么就break,不再进行下面的for循环
        break
fi
复制代码

如果当前遍历的变量类型并不存在,会进行日志输出。
首先,在控制台上面输出unit64_t not found(我们假设当前检测的uint64_t类型不存在)。
然后,把生成的检测数据类型的c源文件以及便一直令保存到NGX_AUTOCONF_ERR文件中,便于进行错误分析。

8). 循环结束后的处理
这里要分三种种情况,如下:

① ``ngx_typengx_types都不存在。那么执行下面的脚本:

if [ $ngx_found = no ]; then
    echo
    echo "$0: error: can not define $ngx_type"

    exit 1
fi
复制代码

这部分脚本会向控制台输出一行错误信息,告诉nginx不能使用当前的变量类型,然后结束脚本。

ngx_type存在。如果是这种情况的话,ngx_found的值是yes,这样的话,auto/types/typedef脚本就直接结束了。

③ ngx_type类型不存在,但是ngx_types存在。这个时候ngx_found的值是ngx_types的值。所以会执行下面的脚本:




    
if [ $ngx_found != yes ]; then
    echo "typedef $ngx_found  $ngx_type;"   >> $
fi
复制代码

也就是向NGX_AUTO_CONFIG_H头文件中生成一个typedef语句。如下:

typedef $ngx_types  $ngx_type;
复制代码

也即是把ngx_type作为$ngx_types的别名,这样程序中就可以一直使用ngx_type这种类型。
对于本例来说,假设满足第种条件的话,就会生成一个如下的typedef语句:

typedef u_int64_t uint64_t;
复制代码

到此为止,我们已经分析完了auto/types/typedef脚本。

总结

本文详细的分析了auto/types/sizeof脚本的功能:测试一个c语言数据类型在特定操作系统上的长度,根据长度进行不同的操作。
其实我们通过这几篇文章可以发现一个东东,Nginx的许多脚本都是自动生成的,说实话,我以前看的源码比较少,也没有关注过这种大型工程的配置文件,真的是一种非常巧妙的方法,我们可以多多借鉴。
后面的文章我们会接着分析nginx的其他辅助脚本,敬请期待。顺便关注我的个公众号(Nginx源码分析)。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/36114
 
502 次点击