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事件
相關文章
相關標籤/搜索