php-fpm初始化失败,FPM的初始化 - [ PHP7的内核剖析 ] - 在线原生手册 - php中文网
FPM的初始化
接下來(lái)看下fpm的啟動(dòng)流程,從main()函數(shù)開(kāi)始://sapi/fpm/fpm/fpm_main.cint?main(int?argc,?char?*argv[]){
...????//注冊(cè)SAPI:將全局變量sapi_module設(shè)置為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進(jìn)程的操作,master進(jìn)程不會(huì)走到下面
parent?=?0;
...
}
fpm_init()主要有以下幾個(gè)關(guān)鍵操作:
(1)fpm_conf_init_main():
解析php-fpm.conf配置文件,分配worker pool內(nèi)存結(jié)構(gòu)并保存到全局變量中:fpm_worker_all_pools,各worker pool配置解析到fpm_worker_pool_s->config中。
(2)fpm_scoreboard_init_main():?分配用于記錄worker進(jìn)程運(yùn)行信息的共享內(nèi)存,按照worker pool的最大worker進(jìn)程數(shù)分配,每個(gè)worker pool分配一個(gè)fpm_scoreboard_s結(jié)構(gòu),pool下對(duì)應(yīng)的每個(gè)worker進(jìn)程分配一個(gè)fpm_scoreboard_proc_s結(jié)構(gòu),各結(jié)構(gòu)的對(duì)應(yīng)關(guān)系如下圖。
(3)fpm_signals_init_main():static?int?sp[2];int?fpm_signals_init_main(){????struct?sigaction?act;
//創(chuàng)建一個(gè)全雙工管道
if?(0?>?socketpair(AF_UNIX,?SOCK_STREAM,?0,?sp))?{????????return?-1;
}????//注冊(cè)信號(hào)處理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;
}
這里會(huì)通過(guò)socketpair()創(chuàng)建一個(gè)管道,這個(gè)管道并不是用于master與worker進(jìn)程通信的,它只在master進(jìn)程中使用,具體用途在稍后介紹event事件處理時(shí)再作說(shuō)明。另外設(shè)置master的信號(hào)處理handler,當(dāng)master收到SIGTERM、SIGINT、SIGUSR1、SIGUSR2、SIGCHLD、SIGQUIT這些信號(hào)時(shí)將調(diào)用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];????//將信號(hào)通知寫(xiě)入管道sp[1]端
write(sp[1],?&s,?sizeof(s));
...
}
(4)fpm_sockets_init_main()
創(chuàng)建每個(gè)worker pool的socket套接字。
(5)fpm_event_init_main():
啟動(dòng)master的事件管理,fpm實(shí)現(xiàn)了一個(gè)事件管理器用于管理IO、定時(shí)事件,其中IO事件通過(guò)kqueue、epoll、poll、select等管理,定時(shí)事件就是定時(shí)器,一定時(shí)間后觸發(fā)某個(gè)事件。
在fpm_init()初始化完成后接下來(lái)就是最關(guān)鍵的fpm_run()操作了,此環(huán)節(jié)將fork子進(jìn)程,啟動(dòng)進(jìn)程管理器,另外master進(jìn)程將不會(huì)再返回,只有各worker進(jìn)程會(huì)返回,也就是說(shuō)fpm_run()之后的操作均是worker進(jìn)程的。int?fpm_run(int?*max_requests){????struct?fpm_worker_pool_s?*wp;
for?(wp?=?fpm_worker_all_pools;?wp;?wp?=?wp->next)?{????????//調(diào)用fpm_children_make()?fork子進(jìn)程
is_parent?=?fpm_children_create_initial(wp);
if?(!is_parent)?{????????????goto?run_child;
}
}????//master進(jìn)程將進(jìn)入event循環(huán),不再往下走
fpm_event_loop(0);
run_child:?//只有worker進(jìn)程會(huì)到這里
*max_requests?=?fpm_globals.max_requests;????return?fpm_globals.listening_socket;?//返回監(jiān)聽(tīng)的套接字}
在fork后worker進(jìn)程返回了監(jiān)聽(tīng)的套接字繼續(xù)main()后面的處理,而master將永遠(yuǎn)阻塞在fpm_event_loop(),接下來(lái)分別介紹master、worker進(jìn)程的后續(xù)操作。
總結(jié)
以上是生活随笔為你收集整理的php-fpm初始化失败,FPM的初始化 - [ PHP7的内核剖析 ] - 在线原生手册 - php中文网的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用python画大雄_python制作斗
- 下一篇: java 按位_Java中的按位运算