一、主启动流程

  1. 流程图
  2. 主要函数
  • ngx_get_options
    解析命令参数
  • ngx_process_options
    配置前缀、前缀、配置文件、配置参数等字符串
  • ngx_add_inherited_sockets
    在进行平滑升级时,将通过“NGINX”环境变量将监听的fd传递给新的进程,用于初始化新进程的cycle->listening结构体。
  • ngx_init_cycle
  • 更新服务器时区和时间
•  tp = ngx_timeofday();
 tp->sec = 0;
 ngx_time_update();
  • 分配一个新的pool和cycle
•  pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
 cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
  • 初始化配置前缀、前缀、配置文件、配置参数等字符串,从旧的old_cycle里边将一些数据拷贝给cycle对象初始化paths数组
ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *);

  • 保存nginx所有要操作的目录,如果有目录不存在,则创建,创建失败则nginx启动失败,调用ngx_add_path添加。eg.proxy_temp_path为存储承载从代理服务器接收到的数据的临时文件定义目录,该路径需要加入path数组。
  • 初始化config_dump数组
•  ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t);
 ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,
 ngx_str_rbtree_insert_value);
  • 初始化open_files数组
ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t);

  • 保存nginx要打开的文件,调用ngx_conf_open_file接口添加。eg.nginx的日志文件路径需要保存在该数组。
  • 初始化shared_memory链表
ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t);

  • 保存nginx要使用的共享内存信息,调用ngx_shared_memory_add接口添加。
  • 根据old_cycle的listening,初始化新的cycle->listening。
•  if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))
 != NGX_OK)
 {
 ngx_destroy_pool(pool);
 return NULL;
 }
  • 初始化resuable_connections_queue队列。
    ngx_queue_init(&cycle->reusable_connections_queue);
  • 调用core模块的create_conf() , 配置存于cycle的conf_ctx数组中,键值为编译后的核心模块的index编号。
•  if (module->create_conf) {
 rv = module->create_conf(cycle);
 if (rv == NULL) {
 ngx_destroy_pool(pool);
 return NULL;
 }
 //[核心模块]配置为一级,索引为模块id
 cycle->conf_ctx[cycle->modules[i]->index] = rv;
 }
  • 配置解析
  • 遍历open_files链表中的每一个文件并打开
•  file[i].fd = ngx_o
 pen_file(file[i].name.data,
 NGX_FILE_APPEND,
 NGX_FILE_CREATE_OR_OPEN,
 NGX_FILE_DEFAULT_ACCESS);
  • 创建共享内存并初始化(新旧shared_memory链表的比较,相同的共享内存保留,旧的不同的共享内存被释放,新的被创建)。
  • 创建新的监听套接字,对old_cycle中存在的套接字进行继承,对不存在的进行新建。
•  if (ngx_open_listening_sockets(cycle) != NGX_OK) {
 goto failed; }
  • 提交新的cycle配置,并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)。
•  if (ngx_init_modules(cycle) != NGX_OK) {
 /* fatal */
 exit(1);
 }
  • 释放old_cycle中多余的shared_memory。
  • 释放old_cycle中不使用的监听套接字。
  • 释放old_cycle中多余的open_files。
  • old_cycle的清理。

二、master进程

  1. ngx_master_process_cycle流程
  • 信号屏蔽
•  if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
 “sigprocmask() failed”);
 }
sigemptyset(&set);
  • 修改进程名
•  ngx_setproctitle(title);
  • 启动worker进程
•  ngx_start_worker_processes(cycle, ccf->worker_processes,
 NGX_PROCESS_RESPAWN);
 ngx_start_cache_manager_processes(cycle, 0);
  • 进入主循环
  1. 主循环流程图

三、worker进程

  1. ngx_worker_process_init初始化
  • 初始化换进变量
• ngx_set_environment(cycle, NULL);
  • 设置进程优先级
•  setpriority(PRIO_PROCESS, 0, ccf->priority);
  • 设置文件句柄数量限制
•  setrlimit(RLIMIT_NOFILE, &rlmt);
  • 设置core_file文件
•  setrlimit(RLIMIT_CORE, &rlmt);
  • 用户组设置
•  setgid(ccf->group);
 initgroups(ccf->username, ccf->group);
 setuid(ccf->user);
  • 设置cpu亲和
•  ngx_get_cpu_affinity(worker);
 ngx_setaffinity(cpu_affinity, cycle->log);
  • 设置信号屏蔽
•  sigemptyset(&set);
 sigprocmask(SIG_SETMASK, &set, NULL);
  • 调用init_process()
•  cycle->modules[i]->init_process(cycle);
  • channel设置,关闭别人的fd[1],保留别人的fd[0]用于互相通信。自己的fd[1]接收master进程的消息。channel事件加入epoll。
• for (n = 0; n < ngx_last_process; n++) {
 close(ngx_processes[n].channel[1]);
 }
 close(ngx_processes[ngx_process_slot].channel[0]);
 ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
 ngx_channel_handler)