nginx主要流程(未完成)

nginx的main启动:初始化master进程信息

输入图片说明

  • 解析命令:ngx_get_options()
    • 解析启动传入的参数argv
      • 若是有p,则初始化前缀路径全局变量 ngx_prefix
      • 若是有c,则初始化配置文件全局变量 ngx_conf_file
      • 若是有g,则初始化全局指令全局变量 ngx_conf_params
      • 若是有s,则初始化信号全局变量 ngx_signal
        • ngx_process = NGX_PROCESS_SIGNALLER
        • ngx_signal=stop或quit或reopen或reload
  • 初始化时间:ngx_time_init()
    • 初始化ngx_cached_err_log_time的长度
    • 初始化ngx_cached_http_time
    • 初始化ngx_cached_http_log_time
    • 初始化ngx_cached_http_log_iso8601
    • 初始化ngx_cached_syslog_time
    • 初始化ngx_cached_time的地址
    • 调用全局变量 ngx_time_update=&cached_time[slot],初始化时间:
      • 获取ngx_time_lock锁
      • 获取linux的时间timeval,解析成ngx_current_msec
      • 初始化cached_time的值
      • 释放ngx_time_lock锁
  • 若是有NGX_PCRE,则初始化prel的正则功能能:ngx_regex_init()
  • 初始化日志:ngx_log_init()
    • 打开log日志,若是日志不存在。则将日志指向stderr
  • 若是有NGX_OPENSSL,初始化SSL:ngx_ssl_init()
  • 初始化内存池1024B:ngx_create_pool()
  • 保存命令:ngx_save_argv()
    • 保存命令行数据到全局变量ngx_argv 中
  • 保存命令行的数据到ngx_cycle_s中:ngx_process_options()
    • 将前缀:ngx_prefix添加到ngx_cycle_s.conf_prefix
    • 将命令行配置文件:ngx_conf_file添加到ngx_cycle_s.conf_file
    • 将全局指令ngx_conf_params添加到ngx_cycle_s.conf_param
  • 设置进程环境:ngx_os_init()
    • 如内存页面大小 ngx_pagesize , ngx_cacheline_size , 最大链接数 ngx_max_sockets 等
  • 初始化CRC表:ngx_crc32_table_init()
  • 初始化slab数据:ngx_slab_sizes_init()
  • 初始化继承的套接字链接池:ngx_add_inherited_sockets()
    • 解析环境变量 NGINX_VAR = "NGINX" 中的 sockets,并保存至 ngx_cycle.listening 数组;
    • 设置继承套接字 ngx_inherited = 1;
    • 调用 ngx_set_inherited_sockets() 逐一对 ngx_cycle.listening 数组中的 sockets 进行设置;
      • 设置监听文件符的sockaddr空间
      • 设置监听文件符的socklen空间
      • 经过getsockname()获取监听套接字的地址
      • 经过getsockname()获取监听套接字的地址
  • ngx_preinit_modules()
    • 初始化每一个 module 的 index,并计算 ngx_max_module
  • 初始化master的ngx_cycle_s :ngx_init_cycle()
    • 更新 timezone 和 time
    • 建立内存池
    • 给 cycle 指针分配内存
    • 保存安装路径,配置文件,启动参数等
    • 初始化文件句柄
    • 初始化共享内存
    • 初始化链接队列
    • 保存 hostname
    • 调用各 NGX_CORE_MODULE 的 create_conf 方法,建立模块的上下文配置内存空间
    • 解析配置文件,替换模块的上下文配置
    • 调用各NGX_CORE_MODULE的init_conf方法,检测模块的上下文配置是否设置彻底,没有设置的参数设置为默认值
    • 打开新的文件句柄
    • 建立共享内存
    • 处理监听socket
    • 建立socket并监听:ngx_open_listening_sockets(cycle)
      • for i<5
      • for cycle->listening.elts
        • 非继承
        • 建立socket
        • 设置socket套接字为可重复使用
        • bind套接字到地址上
        • listen监听套接字,将其放到backlog上
      • end for cycle->listening.elts
      • end for
    • 关闭不须要的socket
    • 关闭不须要的共享内存
    • 关闭不须要的文件
    • ngx_init_modules()-->模块初始化函数init_module()
  • 如有信号,则进入 ngx_signal_process() 处理
  • 调用 ngx_init_signals() 初始化信号,主要完成信号处理程序的注册
  • 进入主循环:ngx_single_process_cycle() 和 ngx_master_process_cycle()

主循环初始化后的运行:ngx_master_process_cycle

  • 阻塞nginx的消息
  • 设置进程名称
  • 启动工做进程ngx_start_worker_processes
    • 循环
    • 调用:ngx_spawn_process() 建立 "worker process":
      • 经过socketpair() 获取UNIX域套接字传输管道,即管道
      • 设置管道为非阻塞模式:ngx_nonblocking()
      • 设置管道为异步模式:ioctl()
      • 设置异步 I/O 的全部者:fcntl()
      • fork()启动子进程,并执行进程的初始化回调函数:proc(cycle, data)
        • ngx_worker_process_cycle
      • 设置 ngx_processes[s] 相关属性
    • 通知以前的work进程新work进程建立完毕 ngx_pass_open_channel(cycle, &ch);
      • 经过管道发送消息:ngx_write_channel()-->sendmsg()
    • 结束循环
  • 启动cache管理进程ngx_start_cache_manager_processes
    • 调用:ngx_spawn_process() 建立 "cache manager process":
      • 经过socketpair() 获取UNIX域套接字,即管道
      • 设置管道为非阻塞模式:ngx_nonblocking()
      • 设置管道为异步模式:ioctl()
      • 设置异步 I/O 的全部者:fcntl()
      • fork()启动子进程,并执行进程的初始化回调函数:proc(cycle, data)
        • ngx_cache_manager_process_cycle
      • 设置 ngx_processes[s] 相关属性
    • work建立成功,通知以前的全部work进程新进程建立完毕 ngx_pass_open_channel(cycle, &ch);
      • 经过管道发送消息:ngx_write_channel()-->sendmsg()
  • 循环等待信号:
    • setitimer()阻塞一段时间等待进程启动
    • sigsuspend()阻塞等待新号
    • ngx_time_update()刷新新时间
    • 若是有 worker 进程由于 SIGCHLD 信号退出了,则重启 worker 进程
    • master 进程退出。若是全部 worker 进程都退出了,而且收到 SIGTERM 信号或 SIGINT 信号或 SIGQUIT 信号等,master 进程开始处理退出
    • 处理ngx_terminate、ngx_quit、ngx_reconfigure、ngx_restart、ngx_reopen、ngx_change_binary、ngx_noaccept信号

工做进程的运行流程(初始化回调函数):ngx_worker_process_cycle

work进程的cycle不须要在初始化ngx_listen_t信息:socket、bind、listen。只须要绑定一个读的处理函数linux

  • ngx_worker_process_init()初始化进程信息
    • 初始化环境变量
    • 设置进程优先级
    • 设置文件句柄数量限制
    • 设置 core_file 文件
    • 用户组设置
    • cpu 亲和度设置
    • 设定工做目录
    • 设置随机种子数
    • 初始化监听状态
    • 调用各模块的init_process方法进行初始化(这里会初始化 epoll)
    • 关闭其它进程的fd[1],保留别人的fd[0]用于互相通讯。关闭本身的fd[0],保留本身的fd[1]接收master进程的消息。
    • 监听管道读事件:ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler)
      • 获取链接文件描述符:ngx_get_connection()
      • 初始化读写内存
      • 添加管道读事件回调函数:ngx_channel_handler 到读事件NGX_READ_EVENT
        • 经过 recvmsg() 阻塞获取master进程发送的消息
      • 这里用来接受master进程的发送启动成功的消息
  • 循环执行事件和监听信号
    • ngx_process_events_and_timers()执行事件
      • ngx_trylock_accept_mutex 当获取到标志位后才进行 accept 事件注册。
      • 执行进程事件ngx_process_events(cycle, timer, flags)。将epoll准备好的读写放到nginx的事件列表中
      • 释放 accept_mutex 锁。
      • 处理定时器事件
      • ngx_event_process_posted(cycle, &ngx_posted_accept_events) 处理 ngx_posted_events和ngx_posted_accept_events 队列的事件
    • 监听ngx_terminate、ngx_quit、ngx_reopen信号

进程事件处理函数:执行回调函数ngx_process_events

暂无

acceptd处理函数:ngx_event_process_posted

void
ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)
{
    ngx_queue_t  *q;
    ngx_event_t  *ev;

    while (!ngx_queue_empty(posted)) {

        q = ngx_queue_head(posted);
        ev = ngx_queue_data(q, ngx_event_t, queue);

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                      "posted event %p", ev);

        ngx_delete_posted_event(ev);//删除事件

        ev->handler(ev);//事件处理
    }
}
  • 全局事件队列:
    • ngx_posted_accept_events: 接受事件队列
    • ngx_posted_events: 读、写事件丢列
    • NGX_READ_EVENT:读类型nginx事件
    • NGX_POST_EVENTS:写类型nginx事件
相关文章
相关标签/搜索