Home  >  Article  >  Backend Development  >  PHP kernel SAPI exploration example sharing

PHP kernel SAPI exploration example sharing

小云云
小云云Original
2018-03-08 10:57:411355browse

As a simple and powerful language, PHP can provide many language features suitable for the Web. Starting from practice, after exploring the principle of weakly typed variables, Wang Shuai will continue to take you to clarify some common parts of the PHP kernel. This issue is an in-depth understanding of SAPI.

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, 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:

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 all calls will be made at the same time. The RINT function registered by the module calls each extension's request initialization function to set 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 until the script is completed, or it may be completed by calling the die() or exit() function

The fourth phase, when the PHP life cycle ends, PHP_MSHUTDOWN_FUNCTION recycles the module. This is for each Extended module shutdown function, 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-thread 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)

Multiprocess mode can build PHP into the Web Server. PHP It can be compiled into the prefork MPM mode and APXS module under Apache. When Apache is started, it will fork many child processes, and each child 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 execute multiple requests (RINT/RSHUTDOWN) after calling MINT to start. MSHUTDOWN will be called for the recycling phase only after Apache is shut down or the process ends.

Figure 4. Life cycle of multi-process


In the multi-process model, each sub-process runs independently without sharing code and data, so a sub-process terminates, exits and restarts Generation will not affect the stability of other child processes.

3. Multithreaded mode (Multithreaded)

Apache2's Worker MPM adopts a multi-threading model, creating multiple threads under one process and executing them in the same process address space.

Figure 5. Multi-threaded life cycle

4. FastCGI mode

In the Nginx+PHP-FPM we use, we use the FastCGI mode. Fastcgi is a special CGI mode is a resident process type of CGI. It can fork multiple processes after running. It does not need to spend time dynamically fork sub-processes, and there is no need to call MINT/MSHUTDOWN for every request. PHP manages and schedules FastCGI's process pool through PHP-FPM. Nginx and PHP-FPM communicate through local TCP Socket and Unix Socket.

Figure 6. FastCGI mode life cycle

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.laruence.com/2008/09/23/539.html

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编写扩展,并在生命周期中找到提高系统性能的方式。

相关推荐:

详解PHP内核解释器的执行

PHP内核-简单讲解PHP灵魂HashTble

PHP内核--探究内存管理与缓存机制的图文详解

The above is the detailed content of PHP kernel SAPI exploration example sharing. For more information, please follow other related articles on the PHP Chinese website!

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