(一)nginx-初始化流程

(一)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 
#include 
#include 
#include 
#include 
#include 
#include 

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-初始化流程)