Home  >  Article  >  Backend Development  >  In-depth understanding of PHP kernel (2) SAPI exploration, in-depth understanding of sapi_PHP tutorial

In-depth understanding of PHP kernel (2) SAPI exploration, in-depth understanding of sapi_PHP tutorial

WBOY
WBOYOriginal
2016-07-12 09:05:22969browse

In-depth understanding of PHP kernel (2), SAPI exploration, in-depth understanding of sapi

In the last article, I introduced you to an in-depth understanding of PHP kernel (1). I believe you will learn more through this article. Let's learn some knowledge. Continue to pay attention to this article about PHP kernel knowledge.

SAPI is the abbreviation of Server Application Programming Interface. PHP provides a set of interfaces through SAPI for data interaction between applications and the PHP kernel.

To put it simply, just like the input and output of a function, we execute a piece of PHP code through the Linux command line. The essence is that the Linux Shell passes in a set of parameters through PHP's SAPI. After the Zend engine executes, it returns to the shell. The process displayed by the shell. Similarly, PHP is called through Apache, and data is passed to SAPI through the Web server. After the Zend engine is executed, it is returned to Apache, and Apache displays it on the page.


Figure 1. PHP architecture diagram

PHP provides many forms of interfaces, including apache, apache2filter, apache2handler, caudium, cgi, cgi-fcgi, cli, cli-server, continuity, embed, isapi, litespeed, milter, nsapi, phttpd pi3web, roxen, thttpd , tux and webjames. But there are only 5 commonly used forms, CLI/CGI (command line), Multiprocess (multi-process), Multithreaded (multi-threaded), FastCGI and Embedded (embedded).

PHP provides a function to view the current SAPI interface type:

Copy code The code is as follows:
string php_sapi_name (void)

PHP running and loading

No matter which SAPI is used, before and after PHP executes the script, it contains a series of events: Module's Init (MINT) and Shutdown (MSHUTDOWN), Request's Init (RINT) and Shutdown (RSHUTDOWN). The first phase is the PHP module initialization phase (MINT), which can initialize extended internal variables, allocate resources, and register resource processors. This process is only executed once during the entire PHP instance life cycle.

What is a PHP module? Through the PHP architecture diagram above, you can use the get_loaded_extensions function in PHP to view all compiled and loaded modules/extensions, which is equivalent to php -m in CLI mode.

Take PHP’s Memcached extension source code as an example:

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; 
}

The second stage is the request initialization stage (RINT). After the module is initialized and activated, the PHP running environment will be created, and the RINT functions registered by all modules will be called. The request initialization function of each extension will be called to set a specific environment. variables, allocate resources, or perform other tasks such as auditing.

PHP_RINIT_FUNCTION(memcached) { 
 /* 执行一些关于请求的初始化 */ 
 return SUCCESS; 
}

In the third stage, after the request processing is completed, PHP_RSHUTDOWN_FUNCTION will be called for recycling. This is the request closing function of each extension to perform the final cleanup work. The Zend engine performs a cleanup process, garbage collection, and unsets every variable used during previous requests. The request may be completed by executing the script or by calling the die() or exit() function

In the fourth stage, when the PHP life cycle ends, PHP_MSHUTDOWN_FUNCTION recycles the module. This is the module shutdown function of each extension, which is used to shut down its own kernel subsystem.

PHP_MSHUTDOWN_FUNCTION(memcached) { /* 执行关于模块的销毁工作 */ UNREGISTER_INI_ENTRIES(); return SUCCESS; }

Common operating modes

There are five common SAPI modes:

CLI and CGI mode (single process mode)
Multi-process mode
Multi-threaded mode
FastCGI mode
Embedded

1. CLI/CGI mode

Both CLI and CGI belong to single-process mode, and the life cycle of PHP is completed in one request. That is to say, every time a PHP script is executed, the four INT and Shutdown events mentioned in the second part will be executed.

Figure 2. CGI/CLI life cycle

2. Multiprocess mode (Multiprocess)

Multi-process mode can build PHP into the Web Server. PHP can be compiled into the prefork MPM mode and APXS module under Apache. When Apache is started, it will fork many sub-processes, and each sub-process has its own independent process address space. .


Figure 3. Multi-process mode life cycle

In a child process, the life cycle of PHP is to call MINT to start and execute multiple requests (RINT/RSHUTDOWN). After Apache is shut down or the process ends, MSHUTDOWN will be called for the recycling phase.

Figure 4. Life cycle of multiple processes

In the multi-process model, each sub-process runs independently without sharing code or data. Therefore, the termination, exit and regeneration of one sub-process will not affect the stability of other sub-processes.

3. Multithreaded mode (Multithreaded)

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


图5. 多线程生命周期

4. FastCGI模式

在我们用的Nginx+PHP-FPM用的就是FastCGI模式,Fastcgi是一种特殊的CGI模式,是一种常驻进程类型的CGI,运行后可以Fork多个进程,不用花费时间动态的Fork子进程,也不需要每次请求都调用MINT/MSHUTDOWN。PHP通过PHP-FPM来管理和调度FastCGI的进程池。Nginx和PHP-FPM通过本地的TCP Socket和Unix Socket 进行通信。


图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. 内嵌模式(Embedded)

Embed SAPI是一种特殊的SAPI,允许在C/C++语言中调用PHP提供的函数。这种SAPI和CLI模式一样,按照Module Init => Request Init => Request => Request Shutdown => Module Shutdown的模式运行。

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

详细请见: http://www.bkjia.com/article/74641.htm

SAPI的运行机制

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

static sapi_module_struct cgi_sapi_module = { 
 "cgi-fcgi",   /* 输出给php_info()使用 */ "CGI/FastCGI",   /* pretty name */ 
 php_cgi_startup,  /* startup 当SAPI初始化时,首先会调用该函数 */ 
 php_module_shutdown_wrapper, /* shutdown 关闭函数包装器,它用来释放所有的SAPI的数据结构、内存等,调用php_module_shutdown */ 
 sapi_cgi_activate,  /* activate 此函数会在每个请求开始时调用,它会做初始化,资源分配 */ 
 sapi_cgi_deactivate,  /* deactivate 此函数会在每个请求结束时调用,它用来确保所有的数据都得到释放 */ 
 sapi_cgi_ub_write,  /* unbuffered write 不缓存的写操作(unbuffered write),它是用来向SAPI外部输出数据 */ 
 sapi_cgi_flush,   /* flush 刷新输出,在CLI模式下通过使用C语言的库函数fflush实现*/ NULL,    /* get uid */ 
 sapi_cgi_getenv,  /* getenv 根据name查找环境变量 */ 
 php_error,   /* error handler 注册错误处理函数 */ 
 NULL,    /* header handler PHP调用header()时候被调用 */ 
 sapi_cgi_send_headers,  /* send headers handler 发送头部信息*/ 
 NULL,    /* send header handler 发送一个单独的头部信息 */ 
 sapi_cgi_read_post,  /* read POST data 当请求的方法是POST时,程序获取POST数据,写入$_POST数组 */ 
 sapi_cgi_read_cookies,  /* read Cookies 获取Cookie值 */ 
 sapi_cgi_register_variables, /* register server variables 给$_SERVER添加环境变量 */ 
 sapi_cgi_log_message,  /* Log message 输出错误信息 */ 
 NULL,    /* Get request time */ 
 NULL,    /* Child terminate */ 
 STANDARD_SAPI_MODULE_PROPERTIES 
}; 

由上面代码可见,PHP的SAPI像是面向对象中基类,SAPI.h和SAPI.c包含的函数是抽象基类的声明和定义,各个服务器用的SAPI模式,则是继承了这个基类,并重新定义基类方法的子类。

总结

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

了解PHP的SAPI机制意义重大,帮助我们理解PHP的生命周期,并了解如何更好的通过C/C++为PHP编写扩展,并在生命周期中找到提高系统性能的方式。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1069345.htmlTechArticle深入理解PHP内核(二)之SAPI探究,深入理解sapi 在上篇文章给大家介绍了深入了解PHP内核(一),相信大家通过本文多多少少都学到些知识吧...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn