宝哥软件园

对PHP内核的深刻理解(二)SAPI研究

编辑:宝哥软件园 来源:互联网 时间:2021-09-22

在上一篇文章中,我介绍了您对php内核(I)的深刻理解。相信通过这篇文章,你或多或少会学到一些知识。继续关注这篇关于PHP内核知识的文章。

SAPI是服务器应用程序编程接口的缩写。通过PHP SAPI,为PHP内核和PHP内核之间的数据交换提供了一套接口。

简单来说,就像一个函数的输入输出一样,我们通过Linux命令行执行一个PHP代码,本质上就是Linux shell通过PHP的SAPI传入一组参数的过程,由Zend引擎执行后返回到Shell,由Shell显示。同样,PHP通过Apache调用,数据通过Web服务器传入SAPI。由Zend引擎执行后,返回Apache,由Apache显示在页面上。

1.PHP架构图。

PHP提供了多种形式的接口,包括apache、apache2filter、apache2handler、caudium、cgi、cgi-fcgi、cli、cli-server、continuity、embed、isapi、litespeed、milter、nsapi、phttpd pi3web、roxen、thttpd、tux和webjames。但是常用的形式只有五种,CLI/CGI(命令行)、multipract(多进程)、多线程(多线程)、FastCGI和Embedded(嵌入式)。

PHP提供了一个查看当前SAPI界面类型的函数:

复制的代码如下:string php_sapi_name (void)。

运行和加载PHP。

无论使用哪个SAPI,在PHP执行脚本前后,都包含了一系列的事件:Module的Init(MINT)和Shutdown(MSHUTDOWN),Request的Init(RINT)和shut down(rshutdown)。第一阶段是PHP模块初始化阶段(MINT),可以初始化和扩展内部变量,分配资源,注册资源处理器。这个过程在PHP实例的整个生命周期中只执行一次。

什么是PHP模块?根据上面的PHP架构图,可以使用PHP中的get_loaded_extensions函数查看所有编译加载的模块/扩展,相当于CLI模式下的php -m。

以PHP的Memcached扩展源代码为例:

PHP _ MINIT _ FUNCTION(memcached){ Zend _ class _ entry ce;memcpy(memcached _ object _ handlers,zend_get_std_object_handlers(),sizeof(Zend _ object _ handlers));memcached _ object _ handlers . clone _ obj=NULL;/*执行了一些类似的初始化操作*/return SUCCESS;}第二阶段是请求初始化阶段(RINT)。模块初始化激活后,会创建PHP运行环境,同时调用所有模块注册的RINT函数,并调用每个扩展请求初始化函数来设置特定的环境变量、分配资源或执行其他任务,如审计。

PHP _ rinit _ function(memcached){/*执行一些关于请求*/return SUCCESS的初始化;}第三阶段,请求处理完成后,会调用PHP _ rshuttown _ function进行回收,这是每个扩展的请求关闭函数,执行最后的清理工作。Zend引擎为前一个请求中使用的每个变量执行清理过程、垃圾收集和取消设置。请求可以一直执行到脚本完成,也可以通过调用die()或exit()函数来完成。

第四阶段,当PHP生命周期结束时,PHP_MSHUTDOWN_FUNCTION回收模块,这是每个扩展的模块关闭函数,用于关闭自己的内核子系统。

PHP _ mshutdown _ function(memcached){/*销毁模块*/UNREGISTER _ INI _ ENTRIES();返回SUCCESS}常见操作模式。

有五种常见的SAPI模式:

CLI和CGI模式(单进程模式)多进程模式多线程模式FastCGI模式嵌入式。

1.命令行界面/计算机生成接口模式。

CLI和CGI都属于单进程模式,PHP的生命周期在一个请求中完成。也就是说,每次执行一个PHP脚本,第二部分提到的四个INT和Shutdown事件都会被执行。

图2。CGI/CLI生命周期

2.多进程模式(多进程)。

多进程模式可以将PHP构建成Web Server,在Apache下可以将PHP编译成prefork MPM模式和APXS模块。当Apache启动时,许多子进程将被分叉,每个子进程都有自己独立的进程地址空间。

图3。多流程模式生命周期。

在一个子进程中,PHP的生命周期是调用MINT启动,然后执行多个请求(RINT/RSHUTDOWN),然后在Apache关闭或进程结束后调用MSHUTDOWN进行回收。

图4。多流程的生命周期。

在多进程模型中,每个子进程独立运行,没有代码和数据共享。因此,一个子过程退出和再生的终止不会影响其他子过程的稳定性。

3.多线程模式(多线程)。

Apache2的Worker MPM采用多线程模型,在一个进程下创建多个线程,在同一个进程地址空间执行。

图5。多线程生命周期。

4.FastCGI模式。

我们使用的Nginx PHP-FPM是FastCGI模式。Fastcgi是一种特殊的cgi模式,是常驻进程类型的CGI。运行后,它可以Fork多个进程,而无需花费时间在动态Fork子进程上,每次都调用MINT/MSHUTDOWN。通过PHP-FPM管理和调度FastCGI进程池。Nginx和PHP-FPM通过本地的TCP套接字和Unix套接字进行通信。

图6。FastCGI模式生命周期。

PHP-FPM进程管理器初始化自己,并启动几个CGI解释器进程来等待来自Nginx的请求。当客户端请求到达PHP-FPM时,管理器选择一个CGI进程进行处理,Nginx将CGI环境变量和标准输入发送到PHP-CIG子进程。PHP-CGI子流程完成处理后,将标准输出和错误信息返回给Nginx。当PHP-CGI子进程关闭连接时,请求处理就完成了。PHP-CGI子进程正在等待下一个连接。

想象一下CGI的开销。每个Web请求PHP都必须重新解析php.ini,加载所有扩展并初始化所有数据结构。使用FastCGI,当进程启动时,这一切只发生一次。此外,数据库和Memcache之间的连续连接也可以工作。

5.嵌入式模式(嵌入式)。

嵌入式SAPI是一个特殊的SAPI,它允许用C/C语言调用PHP提供的函数。与命令行界面模式相同,该SAPI在模块初始化=请求初始化=请求=请求关闭=模块关闭的模式下运行。

Embed SAPI可以调用PHP丰富的类库,也可以实现高级玩法,比如查看PHP的操作码(PHP执行的中间代码,Zend引擎指令,由PHP代码生成)。

详情见://www . JB 51 . net/article/74641 . htm。

SAPI的运行机制。

我们以CGI为例,看看SAPI的运行机制。

static SAPI _ module _ struct CGI _ SAPI _ module={ ' CGI-fcgi ',/*输出到php_info()使用*/'CGI/fastcgi ',/*漂亮的名字*/PHP _ CGI _ startup,/* startup当SAPI初始化时,这个函数将首先被调用*/PHP _ module _ shut _ wrapper,/* shut关闭函数wrapper,该函数用于释放所有SAPI数据结构和内存,并调用PHP _ module _ shut */SAPI _ CGI _ activate。/* activate此函数将在每个请求开始时调用,它将初始化并分配资源*/SAPI _ CGI _ deactivate,/* deactivate此函数将在每个请求结束时调用,它用于确保释放所有数据*/sapi_cgi_ub_write。/*无缓冲写入(无缓冲写入),用于将数据输出到SAPI之外*/sapi_cgi_flush,/* flush用于刷新输出。在CLI模式下,*/NULL是利用C语言的库函数fflush实现的。/* getuid */SAPI _ CGI _ getenv,/* getenv根据名称查找环境变量*/php_error,/*错误处理程序注册错误处理函数*/NULL,/*调用header()*/SAPI _ CGI _ send _ headers时调用header处理程序php,/* send header处理程序发送头信息*/NULL,/* send header处理程序发送单独的头消息*/SAPI _ CGI _ read _ post,/*读取POST数据当请求的方法是POST时,程序获取POST数据并将其写入$_POST数组*。/*读取Cookies以获取Cookie值*/SAPI _ CGI _ register _ variables,/*注册服务器变量以将环境变量添加到$_SERVER */sapi_cgi_log_message,/*日志消息输出错误消息*/null,/* getrequesttime */null,/* child terminal */standard _ SAPI _ module _ properties };从上面的代码可以看出,PHP的SAPI就像是面向对象中的一个基类,SAPI.h和SAPI.c中包含的函数是抽象基类的声明和定义,各种服务器使用的SAPI模式继承了这个基类,重新定义了基类方法的子类。

摘要

PHP的SAPI是Zend引擎提供的一套标准交互界面。通过注册初始化、析构器、输入输出接口,我们可以在Zend引擎上运行应用程序,也可以像Apache一样将PHP嵌入Web Server。PHP中常见的SAPI模式有五种,CGI/CLI模式、多进程模式、多线程模式、FastCGI模式和嵌入式模式。

了解PHP的SAPI机制意义重大,有助于我们了解PHP的生命周期,如何通过C/C更好地为PHP编写扩展,找到在生命周期内提升系统性能的方法。

更多资讯
游戏推荐
更多+