PHP内核剖析 常见的SAPI及Embed

参考文献:https://blog.csdn.net/zhuocr/article/details/60328967 、《PHP7内核剖析》秦鹏/著

SAPI:Server Application Programming Interface 服务器端应用编程端口。它就是PHP与其它应用交互的接口,PHP脚本要执行有很多种方式,通过Web服务器,或者直接在命令行下,也可以嵌入在其他程序中。
        SAPI提供了一个和外部通信的接口,常见的SAPI有:cgi 、fast-cgi、cli、isapi、apache 模块的 DLL

目录

1、常见的SAPI介绍

2、Embed

2.1  php_embed_init()

2.2  php_embed_shutdown()


1、常见的SAPI介绍

CGI

CGI即通用网关接口(Common Gateway Interface),一段把网页和web服务器中的执行程序连接起来的程序。它把HTML接收的指令传递给服务器执行程序,再把服务器执行程序的结果返还给HTML页。CGI的跨平台性也极强,几乎能在任何操作系统上运行。

CGI在遇到用户连接请求时要先创建CGI的子进程,然后处理请求,处理完后结束这个子进程。这就是fork-and-execute模式。不过有多少连接请求就有多少CGI子进程,会造成资源的拥挤。

fast-cgi

CGI的升级版本,常住型的CGI,前面介绍过。PHP的Fpm就是FastCGI Process Manager,全称为PHP FastCGI进程管理器。FastCGI的工作原理:

(1)Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)
            (2)FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。
            (3)当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
             (4)FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。

在上述情况中,你可以想象CGI通常有多慢。每一个Web 请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的 好处是,持续数据库连接(Persistent database connection)可以工作。

APACHE2HANDLER
           PHP作为Apache模块,Apache服务器在系统启动后,预先生成多个进程副本驻留在内存中,一旦有请求出现,就立即使用这些空余的子进程进行处理,这样就不存在生成子进程造成的延迟了。这些服务器副本在处理完一次HTTP请求之后并不立即退出,而是停留在计 算机中等待下次请求。对于客户浏览器的请求反应更快,性能较高。


           apache模块的DLL:
           该运行模式是我们以前在windows环境下使用apache服务器经常使用的,而在模块化(DLL)中,PHP是与Web服务器一起启动并运行的。(是apache在CGI的基础上进行的一种扩展,加快PHP的运行效率)

 ISAPI: 
            ISAPI即Internet Server Application Program Interface,是微软提供的一套面向Internet服务的API接口.一个ISAPI的DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个DLL里设置多个用户请求处理函数,此外,ISAPI的DLL应用程序和WWW服务器处于同一个进程中,效率要显著高于CGI。

cli:
           cli是php的命令行运行模式,大家经常会使用它,但是可能并没有注意到(例如:我们在linux下经常使用 “php -m”查找PHP安装了那些扩展就是PHP命令行运行模式;

在windows下使用cli模式从命令行进入www目录,然后运行。

Embed

如果我们自己的第三方程序想使用PHP,那么我们就需要这类SAPI,它在编译后就是普通的库文件(可以选择编译为静态库、共享库),我们可以在其它C/C++应用中调用PHP提供的API甚至可以提供给其它语言处理

2、Embed

编译PHP时通过 --enable-embed=[shared|static]指定库类型,默认是共享库。编译之后可以在PHP安装位置的/lib目录下看到生成的库文件,同时在/include/php/sapi目录下会生成一个存放Embed头文件的目录。

Embed的实现逻辑非常简单,只是把PHP生命周期的几个处理函数进行了封装,它对外提供了两个API。

2.1  php_embed_init()

这个接口主要进行PHP框架的初始化操作,比如TSRM、初始化SAPI、初始化信号处理,另外它还完成了非常重要的两个操作,那就是php_module_startup()、php_request_startup()。

EMBED_SAPI_API int php_embed_init(int argc, char **argv)
{
	zend_llist global_vars;
#ifdef ZTS
  //初始化SAPI
  tsrm_startup(1, 1, 0, NULL);
  (void)ts_resource(0);
  ZEND_TSRMLS_CACHE_UPDATE();
#endif

	zend_signal_startup();

  //初始化SAPI
  sapi_startup(&php_embed_module);
  ...
  //进入module startup阶段
  if (php_embed_module.startup(&php_embed_module)==FAILURE) {
	  return FAILURE;
  }
  ...
  //请求request startup阶段
  if (php_request_startup()==FAILURE) {
	  php_module_shutdown();
	  return FAILURE;
  }
  ...
}

在第三方应用中嵌入PHP时首先需要调用这个接口,然后就可以使用PHP/Zend提供的API完成PHP脚本的执行了。

2.2  php_embed_shutdown()

此接口与php_embed_init()对应,主要完成PHP框架的关闭收尾工作,包括request shutdown、module shutdown两个阶段的操作。

EMBED_SAPI_API void php_embed_shutdown(void)
{
    //关闭请求,request shutdown阶段
	php_request_shutdown((void *) 0);
    //关闭模块
	php_module_shutdown();
	sapi_shutdown();

#ifdef ZTS
    tsrm_shutdown();
	TSRMLS_CACHE_RESET();
#endif

	if (php_embed_module.ini_entries) {
		free(php_embed_module.ini_entries);
		php_embed_module.ini_entries = NULL;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值