《深入理解Nginx:模块开发与架构解析》一1.5 configure详解

    xiaoxiao2021-04-16  230

    1.5 configure详解

    可以看出,configure命令至关重要,下文将详细介绍如何使用configure命令,并分析configure到底是如何工作的,从中我们也可以看出Nginx的一些设计思想。

    1.5.1 configure的命令参数

    使用help命令可以查看configure包含的参数。

    ./configure --help

    这里不一一列出help的结果,只是把它的参数分为了四大类型,下面将会详述各类型下所有参数的用法和意义。

    路径相关的参数表1-2列出了Nginx在编译期、运行期中与路径相关的各种参数。

    编译相关的参数表1-3列出了编译Nginx时与编译器相关的参数。

    依赖软件的相关参数表1-4~表1-8列出了Nginx依赖的常用软件支持的参数。

    模块相关的参数除了少量核心代码外,Nginx完全是由各种功能模块组成的。这些模块会根据配置参数决定自己的行为,因此,正确地使用各个模块非常关键。在configure的参数中,我们把它们分为五大类。

    事件模块。默认即编译进入Nginx的HTTP模块。默认不会编译进入Nginx的HTTP模块。邮件代理服务器相关的mail 模块。其他模块。(1)事件模块表1-9中列出了Nginx可以选择哪些事件模块编译到产品中。

    (2)默认即编译进入Nginx的HTTP模块表1-10列出了默认就会编译进Nginx的核心HTTP模块,以及如何把这些HTTP模块从产品中去除。

    (3)默认不会编译进入Nginx的HTTP模块表1-11列出了默认不会编译至Nginx中的HTTP模块以及把它们加入产品中的方法。

    (4)邮件代理服务器相关的mail模块表1-12列出了把邮件模块编译到产品中的参数。

    5.其他参数configure还接收一些其他参数,表1-13中列出了相关参数的说明。

    1.5.2 configure执行流程

    我们看到configure命令支持非常多的参数,读者可能会好奇它在执行时到底做了哪些事情,本节将通过解析configure源码来对它有一个感性的认识。configure由Shell脚本编写,中间会调用/auto/目录下的脚本。这里将只对configure脚本本身做分析,对于它所调用的auto目录下的其他工具脚本则只做功能性的说明。configure脚本的内容如下:

    #!/bin/sh # Copyright (C) Igor Sysoev # Copyright (C) Nginx, Inc. #auto/options脚本处理configure命令的参数。例如,如果参数是--help,那么显示支持的所有参数格式。options脚本会定义后续工作将要用到的变量,然后根据本次参数以及默认值设置这些变量 . auto/options #auto/init脚本初始化后续将产生的文件路径。例如,Makefile、ngx_modules.c等文件默认情况下将会在<nginx-source>/objs/ . auto/init #auto/sources脚本将分析Nginx的源码结构,这样才能构造后续的Makefile文件 . auto/sources #编译过程中所有目标文件生成的路径由—builddir=DIR参数指定,默认情况下为<nginx-source>/objs,此时这个目录将会被创建 test -d $NGX_OBJS || mkdir $NGX_OBJS #开始准备建立ngx_auto_headers.h、autoconf.err等必要的编译文件 echo > $NGX_AUTO_HEADERS_H echo > $NGX_AUTOCONF_ERR #向objs/ngx_auto_config.h写入命令行带的参数 echo "#define NGX_CONFIGURE \"$NGX_CONFIGURE\"" > $NGX_AUTO_CONFIG_H #判断DEBUG标志,如果有,那么在objs/ngx_auto_config.h文件中写入DEBUG宏 if [ $NGX_DEBUG = YES ]; then have=NGX_DEBUG . auto/have fi #现在开始检查操作系统参数是否支持后续编译 if test -z "$NGX_PLATFORM"; then echo "checking for OS" NGX_SYSTEM=`uname -s 2>/dev/null` NGX_RELEASE=`uname -r 2>/dev/null` NGX_MACHINE=`uname -m 2>/dev/null` #屏幕上输出OS名称、内核版本、32位/64位内核 echo " + $NGX_SYSTEM $NGX_RELEASE $NGX_MACHINE" NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE"; case "$NGX_SYSTEM" in MINGW32_*) NGX_PLATFORM=win32 ;; esac else echo "building for $NGX_PLATFORM" NGX_SYSTEM=$NGX_PLATFORM fi #检查并设置编译器,如GCC是否安装、GCC版本是否支持后续编译nginx . auto/cc/conf #对非Windows操作系统定义一些必要的头文件,并检查其是否存在,以此决定configure后续步骤是否可以成功 if [ "$NGX_PLATFORM" != win32 ]; then . auto/headers fi #对于当前操作系统,定义一些特定的操作系统相关的方法并检查当前环境是否支持。例如,对于Linux,在这里使用sched_setaffinity设置进程优先级,使用Linux特有的sendfile系统调用来加速向网络中发送文件块 . auto/os/conf #定义类UNIX 操作系统中通用的头文件和系统调用等,并检查当前环境是否支持 if [ "$NGX_PLATFORM" != win32 ]; then . auto/unix fi

    最核心的构造运行期modules的脚本。它将会生成ngx_modules.c文件,这个文件会被编译进Nginx中,其中它所做的唯一的事情就是定义了ngx_modules数组。ngx_modules指明Nginx运行期间有哪些模块会参与到请求的处理中,包括HTTP请求可能会使用哪些模块处理,因此,它对数组元素的顺序非常敏感,也就是说,绝大部分模块在ngx_modules数组中的顺序其实是固定的。例如,一个请求必须先执行ngx_http_gzip_filter_module模块重新修改HTTP响应中的头部后,才能使用ngx_http_header_filter模块按照headers_in结构体里的成员构造出以TCP流形式发送给客户端的HTTP响应头部。注意,我们在--add-module=参数里加入的第三方模块也在此步骤写入到ngx_modules.c文件中了. auto/modules

    #conf脚本用来检查Nginx在链接期间需要链接的第三方静态库、动态库或者目标文件是否存在 . auto/lib/conf ``

    处理Nginx安装后的路径case ".$NGX_PREFIX" in

    .) NGX_PREFIX=${NGX_PREFIX:-/usr/local/nginx} have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define ;; .!) NGX_PREFIX= ;; *) have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define ;;

    esac

    处理Nginx安装后conf文件的路径 if [ ".$NGX_CONF_PREFIX" != "." ]; then have=NGX_CONF_PREFIX value="\"$NGX_CONF_PREFIX/\"" . auto/define fi 处理Nginx安装后,二进制文件、pid、lock等其他文件的路径可参见configure参数中路径类选项的说明 have=NGX_SBIN_PATH value="\"$NGX_SBIN_PATH\"" . auto/define have=NGX_CONF_PATH value="\"$NGX_CONF_PATH\"" . auto/define have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . auto/define have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" . auto/define have=NGX_HTTP_CLIENT_TEMP_PATH value="\"$NGX_HTTP_CLIENT_TEMP_PATH\"" . auto/define have=NGX_HTTP_PROXY_TEMP_PATH value="\"$NGX_HTTP_PROXY_TEMP_PATH\"" . auto/define have=NGX_HTTP_FASTCGI_TEMP_PATH value="\"$NGX_HTTP_FASTCGI_TEMP_PATH\"" . auto/define have=NGX_HTTP_UWSGI_TEMP_PATH value="\"$NGX_HTTP_UWSGI_TEMP_PATH\"" . auto/define have=NGX_HTTP_SCGI_TEMP_PATH value="\"$NGX_HTTP_SCGI_TEMP_PATH\"" . auto/define 创建编译时使用的objs/Makefile文件 . auto/make #为objs/Makefile加入需要连接的第三方静态库、动态库或者目标文件 . auto/lib/make 为objs/Makefile加入install功能,当执行make install时将编译生成的必要文件复制到安装路径,建立必要的目录 . auto/install #在ngx_auto_config.h文件中加入NGX_SUPPRESS_WARN宏、NGX_SMP宏 . auto/stubs 在ngx_auto_config.h文件中指定NGX_USER和NGX_GROUP宏,如果执行configure时没有参数指定,默认两者皆为nobody(也就是默认以nobody用户运行进程) have=NGX_USER value="\"$NGX_USER\"" . auto/define have=NGX_GROUP value="\"$NGX_GROUP\"" . auto/define #显示configure执行的结果,如果失败,则给出原因 . auto/summary ###1.5.3 configure生成的文件 当configure执行成功时会生成objs目录,并在该目录下产生以下目录和文件:

    |---ngx_auto_headers.h|---autoconf.err|---ngx_auto_config.h|---ngx_modules.c|---src| |---core| |---event| | |---modules| |---os| | |---unix| | |---win32| |---http| | |---modules| | | |---perl| |---mail| |---misc|---Makefile

    上述目录和文件介绍如下。 1)src目录用于存放编译时产生的目标文件。 2)Makefile文件用于编译Nginx工程以及在加入install参数后安装Nginx。 3)autoconf.err保存configure执行过程中产生的结果。 4)ngx_auto_headers.h和ngx_auto_config.h保存了一些宏,这两个头文件会被src/core/ngx_config.h及src/os/unix/ngx_linux_config.h文件(可将“linux”替换为其他UNIX操作系统)引用。 5)ngx_modules.c是一个关键文件,我们需要看看它的内部结构。一个默认配置下生成的ngx_modules.c文件内容如下:

    include

    include

    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_http_module, &ngx_http_core_module, &ngx_http_log_module, &ngx_http_upstream_module, &ngx_http_static_module, &ngx_http_autoindex_module, &ngx_http_index_module, &ngx_http_auth_basic_module, &ngx_http_access_module, &ngx_http_limit_zone_module, &ngx_http_limit_req_module, &ngx_http_geo_module, &ngx_http_map_module, &ngx_http_split_clients_module, &ngx_http_referer_module, &ngx_http_rewrite_module, &ngx_http_proxy_module, &ngx_http_fastcgi_module, &ngx_http_uwsgi_module, &ngx_http_scgi_module, &ngx_http_memcached_module, &ngx_http_empty_gif_module, &ngx_http_browser_module, &ngx_http_upstream_ip_hash_module, &ngx_http_write_filter_module, &ngx_http_header_filter_module, &ngx_http_chunked_filter_module, &ngx_http_range_header_filter_module, &ngx_http_gzip_filter_module, &ngx_http_postpone_filter_module, &ngx_http_ssi_filter_module, &ngx_http_charset_filter_module, &ngx_http_userid_filter_module, &ngx_http_headers_filter_module, &ngx_http_copy_filter_module, &ngx_http_range_body_filter_module, &ngx_http_not_modified_filter_module, NULL

    };

    ngx_modules.c文件就是用来定义ngx_modules数组的。 ngx_modules是非常关键的数组,它指明了每个模块在Nginx中的优先级,当一个请求同时符合多个模块的处理规则时,将按照它们在ngx_modules数组中的顺序选择最靠前的模块优先处理。对于HTTP过滤模块而言则是相反的,因为HTTP框架在初始化时,会在ngx_modules数组中将过滤模块按先后顺序向过滤链表中添加,但每次都是添加到链表的表头,因此,对HTTP过滤模块而言,在ngx_modules数组中越是靠后的模块反而会首先处理HTTP响应(参见第6章及第11章的11.9节)。 因此,ngx_modules中模块的先后顺序非常重要,不正确的顺序会导致Nginx无法工作,这是auto/modules脚本执行后的结果。读者可以体会一下上面的ngx_modules中同一种类型下(第8章会介绍模块类型,第10章、第11章将介绍的HTTP框架对HTTP模块的顺序是最敏感的)各个模块的顺序以及这种顺序带来的意义。 可以看出,在安装过程中,configure做了大量的幕后工作,我们需要关注在这个过程中Nginx做了哪些事情。configure除了寻找依赖的软件外,还针对不同的UNIX操作系统做了许多优化工作。这是Nginx跨平台的一种具体实现,也体现了Nginx追求高性能的一贯风格。 configure除了生成Makefile外,还生成了ngx_modules.c文件,它决定了运行时所有模块的优先级(在编译过程中而不是编码过程中)。对于不需要的模块,既不会加入ngx_modules数组,也不会编译进Nginx产品中,这也体现了轻量级的概念。 相关资源:七夕情人节表白HTML源码(两款)

    最新回复(0)