php-fpm源码解读(草稿)
keyganker opened this issue · comments
通过阅读源码+debug+参考文章一步步了解流程
启动入口,fpm_main.c中的main函数
几个重要的阶段:
一. 初始化: fpm_init函数,这里会调用大量的初始化函数:
1. fpm_php_init_main
2. fpm_stdio_init_main
3. fpm_conf_init_main
4. fpm_unix_init_main
5. fpm_scoreboard_init_main
6. fpm_pctl_init_main
7. fpm_env_init_main
8. fpm_signals_init_main
9. fpm_children_init_main
10. fpm_sockets_init_main
11. fpm_worker_pool_init_main
12. fpm_event_init_main
二. worker初始化和master的event loop: fpm_run
三. 初始化、处理请求: fpm_init_request、fcgi_accept_request、fpm_request_executing、php_execute_script、fpm_request_end、php_request_shutdown、fcgi_finish_request
在fpm_init中初始化,并且打开各个pool中配置的socket网络链接,然后再在fpm_run中fork各个pool中配置的children进程
父进程在fpm_run方法中会进入event loop,使用epoll来监听事件,包括:1个信号管道:处理用户发送的信号,2个常规定时器:子进程伸缩管理定时器(子进程重启相关) 和 子进程健康检查,这样就可以并发的处理以上3类事件
父进程事件监听支持多种方式,可以在php-fpm.conf中通过events.mechanism配置,如果没有配置则会按照如下顺序来选择系统支持的事件处理方式(在第一阶段的fpm_conf_init_main->fpm_conf_post_process->fpm_event_pre_init中执行):
1.kqueue
2.port
3.epoll
4./dev/poll
5.poll
6.select
问: 为什么在master进程中epoll可以处理信号呢?
答:这是因为在第一个阶段的fpm_signals_init_main方法中,创建了一个socketpair,即一对双工的socket;这样当有信号时(如用户输入kill命令),则通过注册的信号处理函数sig_handler,把信号转换为一个字符标识,写入socket[1]中;而在第二阶段中,fpm_event_loop函数中epoll监听了socket[0],这样之前写入socket的事件在epoll就能触发。进而被epoll回调函数处理
子进程接受请求:fcgi_accept_request,这里是用select来处理请求的