用户名: 密码: 忘记密码? 注册
收藏此问题 发表新评论

关于模块加载的过程问题

最近在深入一下php的源码,在许多文章里面了解php的执行过程,在cli的时候,模块加载如下:
在fcgi模式下,模块被加载并执行的过程是如下图:

我通过在mysql模块里面各个函数里面写文件来记录mysql模块的执行过程,发现在cli运行的确是minit->rinit->rshutdown->mshutdown

但在php-fpm情况下(fastcgi)发现启动php-fpm就执行了minit->mshutdown.然后每次请求都会执行rinit->rshutdown,然后kill -SIGINT `pidof php-fpm`的时候却没发现mshutdown,请问这是为什么?

mysql的PHP_MSHUTDOWN_FUNCTION其实就是执行 mysql_server_end();若的确是启动就执行了mshutdown,那不是有问题了吗,谁能解释一下。

php版本:php-5.3.6
昵称: sunceenjoy  时间: 2013-06-13 12:00:45
本帖最后由 sunceenjoy 于 2013-6-13 17:38 编辑

经过进一步查看代码,发现fpm-php(fastcgi)执行过程没错,的确是minit->rinit->rshutdown->mshutdown,只不过需仔细看才会明白出现我上面描述问题的原因:
1.fpm_main.c为入口函数,在1818行前都没有什么问题:main函数处理用户参数的过程,若没参数,则默认要进入主程序了。
2.   1818行: if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, test_conf)) {
        return FAILURE;
    }
这里进行fpm的初始化工作,中间有一个函数:fpm_unix_init_main:
if (fpm_global_config.daemonize) {//如果是后台程序的方式
        switch (fork()) {
            case -1 :
                zlog(ZLOG_SYSERROR, "daemonized fork() failed");
                return -1;
            case 0 ://子进程继续往下
                break;
            default ://父进程,则清理并退出,而就是这个函数会执行各个模块的MSHUTDOWN,于是在我的调试文件里面出现了:
// MINIT,MSHUTDOWN

                fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
                exit(0);
        }
    }
//其实程序若执行到这里的话,对于子进程来说,仅仅是执行了MSHUTDOWN,并且在调试文件里面不会出现:因为父进程替它执行了

//产生新的会话(master process)
setsid();
    .....
3.回到 fpm_main.c:
fcgi_fd = fpm_run(&max_requests);//这里是生成work process(master process的子进程)的地方了
再回到本文主题,在调试文件里面加入进程id,就会发现差异了:

MINIT(父)
MSHUTDOWN(父)
//下面curl localhost/1.php一次就出现一对init,shutdown
RINIT(孙:work process)
RSHUTDOWN(孙 work process)
RINIT(孙:work process)
RSHUTDOWN(孙 work process)
....

//最后kill -SIGTERM `pidof php-fp[m]`
MSHUTDOWN(子:master process)

另外根据代码可知:正常关闭php-fpm请用kill -SIGTERM.

到此已经说明本题了。
昵称: sunceenjoy  时间: 2013-06-13 17:21:50
发表评论
昵称:
内容:
验证: