亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

characters

FPM的初始化

接下來看下fpm的啟動流程,從main()函數(shù)開始:

//sapi/fpm/fpm/fpm_main.cint main(int argc, char *argv[]){
    ...    //注冊SAPI:將全局變量sapi_module設置為cgi_sapi_module
    sapi_startup(&cgi_sapi_module);
    ...    //執(zhí)行php_module_starup()
    if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {        return FPM_EXIT_SOFTWARE;
    }
    ...    //初始化
    if(0 > fpm_init(...)){
        ...
    }
    ...
    fpm_is_running = 1;
    fcgi_fd = fpm_run(&max_requests);//后面都是worker進程的操作,master進程不會走到下面
    parent = 0;
    ...
}

fpm_init()主要有以下幾個關鍵操作:

(1)fpm_conf_init_main():

解析php-fpm.conf配置文件,分配worker pool內存結構并保存到全局變量中:fpm_worker_all_pools,各worker pool配置解析到fpm_worker_pool_s->config中。

(2)fpm_scoreboard_init_main(): 分配用于記錄worker進程運行信息的共享內存,按照worker pool的最大worker進程數(shù)分配,每個worker pool分配一個fpm_scoreboard_s結構,pool下對應的每個worker進程分配一個fpm_scoreboard_proc_s結構,各結構的對應關系如下圖。


(3)fpm_signals_init_main():

static int sp[2];int fpm_signals_init_main(){    struct sigaction act;
    //創(chuàng)建一個全雙工管道
    if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {        return -1;
    }    //注冊信號處理handler
    act.sa_handler = sig_handler;
    sigfillset(&act.sa_mask);    if (0 > sigaction(SIGTERM,  &act, 0) ||        0 > sigaction(SIGINT,   &act, 0) ||        0 > sigaction(SIGUSR1,  &act, 0) ||        0 > sigaction(SIGUSR2,  &act, 0) ||        0 > sigaction(SIGCHLD,  &act, 0) ||        0 > sigaction(SIGQUIT,  &act, 0)) {        return -1;
    }    return 0;
}

這里會通過socketpair()創(chuàng)建一個管道,這個管道并不是用于master與worker進程通信的,它只在master進程中使用,具體用途在稍后介紹event事件處理時再作說明。另外設置master的信號處理handler,當master收到SIGTERM、SIGINT、SIGUSR1、SIGUSR2、SIGCHLD、SIGQUIT這些信號時將調用sig_handler()處理:

static void sig_handler(int signo){    static const char sig_chars[NSIG + 1] = {
        [SIGTERM] = 'T',
        [SIGINT]  = 'I',
        [SIGUSR1] = '1',
        [SIGUSR2] = '2',
        [SIGQUIT] = 'Q',
        [SIGCHLD] = 'C'
    };    char s;
    ...
    s = sig_chars[signo];    //將信號通知寫入管道sp[1]端
    write(sp[1], &s, sizeof(s));
    ...
}

(4)fpm_sockets_init_main()

創(chuàng)建每個worker pool的socket套接字。

(5)fpm_event_init_main():

啟動master的事件管理,fpm實現(xiàn)了一個事件管理器用于管理IO、定時事件,其中IO事件通過kqueue、epoll、poll、select等管理,定時事件就是定時器,一定時間后觸發(fā)某個事件。

在fpm_init()初始化完成后接下來就是最關鍵的fpm_run()操作了,此環(huán)節(jié)將fork子進程,啟動進程管理器,另外master進程將不會再返回,只有各worker進程會返回,也就是說fpm_run()之后的操作均是worker進程的。

int fpm_run(int *max_requests){    struct fpm_worker_pool_s *wp;
    for (wp = fpm_worker_all_pools; wp; wp = wp->next) {        //調用fpm_children_make() fork子進程
        is_parent = fpm_children_create_initial(wp);        
        if (!is_parent) {            goto run_child;
        }
    }    //master進程將進入event循環(huán),不再往下走
    fpm_event_loop(0);
run_child: //只有worker進程會到這里
    *max_requests = fpm_globals.max_requests;    return fpm_globals.listening_socket; //返回監(jiān)聽的套接字}

在fork后worker進程返回了監(jiān)聽的套接字繼續(xù)main()后面的處理,而master將永遠阻塞在fpm_event_loop(),接下來分別介紹master、worker進程的后續(xù)操作。


Previous article: Next article: