美文网首页
(一)nginx-初始化流程

(一)nginx-初始化流程

作者: 爱吃花栗鼠的猫 | 来源:发表于2015-10-15 10:57 被阅读518次

    (一)nginx-初始化流程


    nginx代码结构复杂,但是再复杂的程序都是可认知的,让我们从开始,一步一步来。

    int ngx_cdecl main(int argc, char *const *argv)

    ngx_cdecl是一个空的宏。仅仅是为了平台移植的方便。

    ngx_int_t         i;
     ngx_log_t        *log;
     ngx_cycle_t      *cycle, init_cycle;
     ngx_core_conf_t  *ccf;
     ngx_debug_init();//应该是初始化debug版本,但在linux中,此函数定义为空
    
     if (ngx_strerror_init() != NGX_OK) {
           return 1;
     }
    

    ng_sterror_init 错误初始化函数。进入此函数。

    ngx_int_t
    ngx_strerror_init(void)
    {
    char       *msg;
    u_char     *p;
    size_t      len;
    ngx_err_t   err;
    
    /*
     * ngx_strerror() is not ready to work at this stage, therefore,
     * malloc() is used and possible errors are logged using strerror().
     */
    
    len = NGX_SYS_NERR * sizeof(ngx_str_t);
    //NGX_SYS_NERR是操作系统识别的错误个数,
    //在centos7上是133,编译出的ngin是135,可能nginx是为了做一点空间的冗余。
    
    ngx_sys_errlist = malloc(len);//为错误信息数组分配空间
    if (ngx_sys_errlist == NULL) {
        goto failed;
    }
    //ngx_sys_errlist是一个全局的错误数组,类型为ngx_str_t。
    
    for (err = 0; err < NGX_SYS_NERR; err++) {
        msg = strerror(err);//错误内容
        len = ngx_strlen(msg);//错误信息长度
    
        p = malloc(len);
        if (p == NULL) {
            goto failed;
        }
    
        ngx_memcpy(p, msg, len);
        ngx_sys_errlist[err].len = len;
        ngx_sys_errlist[err].data = p;
    }
    //上面这段很清晰了,完成错误数组初始化。
    return NGX_OK;
    
    failed:
    
    err = errno;
    ngx_log_stderr(0, "malloc(%uz) failed (%d: %s)", len, err, strerror(err));
    
    return NGX_ERROR;
    }
    

    解析命令行参数部分。把参数保存在全局变量中。

    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }
    

    如果命令行中有-h -v -V,则ngx_show_version会为1,在console上会打印help信息。

    if (ngx_show_version) {
    ...
    }
    
    /* TODO */ ngx_max_sockets = -1;
    
    ngx_time_init();
    

    ngx_time_init中的ngx_time_update中有个ngx_trylock函数。

    #define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
    #define ngx_unlock(lock)    *(lock) = 0
    

    其中ngx_atomic_cmp_set定义如下:

    #define ngx_atomic_cmp_set(lock, old, set)                                    \
    __sync_bool_compare_and_swap(lock, old, set)
    
    #define ngx_atomic_fetch_add(value, add)                                      \
    __sync_fetch_and_add(value, add)
    

    里面用到了gcc提供的原子操作。效率如何没做具体的性能测试,可再查下文献。


    gcc原子操作简单测试例子。

    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/select.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    int val = 0;
    int mu = 0;
    
    #define ngx_atomic_cmp_set(lock, old, set)                                    \
        __sync_bool_compare_and_swap(lock, old, set)
    
    #define ngx_atomic_fetch_add(value, add)                                      \
        __sync_fetch_and_add(value, add)
    
    #define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
    #define ngx_unlock(lock)    *(lock) = 0
    
    void* fun1(void *)
    {
        while (1) {
            if (!ngx_trylock(&mu)) {
                return NULL;
            }
            val += 1;
            ngx_unlock(&mu);
    
            printf("fun1: %d\n", val);
            sleep(1);
        }
    }
    
    void* fun2(void *)
    {
        while (1) {
            if (!ngx_trylock(&mu)) {
                return NULL;
            }
            val += 1;
            ngx_unlock(&mu);
    
            printf("fun2: %d\n", val);
            sleep(1);
        }
    }
    
    int main()
    {
        pthread_t p1;
        pthread_t p2;
    
        pthread_create(&p1, NULL, fun1, NULL);
        pthread_create(&p2, NULL, fun2, NULL);
    
        pthread_join(p1, NULL);
        pthread_join(p2, NULL);
    
        return 0;
    }
    

    正则表达式初始化操作

    #if (NGX_PCRE)
        ngx_regex_init();
    #endif
    

    里面是给两个回调函数赋值,分配释放空间。下面说下其中用到的ngx_palloc

    void *
    ngx_palloc(ngx_pool_t *pool, size_t size)
    {
        u_char      *m;
        ngx_pool_t  *p;
    
        if (size <= pool->max) {
    
            p = pool->current;
    
            do {
                m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
    
                if ((size_t) (p->d.end - m) >= size) {
                    p->d.last = m + size;
    
                    return m;
                }
    
                p = p->d.next;
    
            } while (p);
    
            return ngx_palloc_block(pool, size);
        }
    
        return ngx_palloc_large(pool, size);
    }
    

    展开篇幅太大,下一篇说下内存池的理解。

    相关文章

      网友评论

          本文标题:(一)nginx-初始化流程

          本文链接:https://www.haomeiwen.com/subject/uxyocttx.html