Heim  >  Artikel  >  Backend-Entwicklung  >  Teilen von PHP-Kernel-SAPI-Erkundungsbeispielen

Teilen von PHP-Kernel-SAPI-Erkundungsbeispielen

小云云
小云云Original
2018-03-08 10:57:411415Durchsuche

Als einfache und leistungsstarke Sprache kann PHP viele für das Web geeignete Sprachfunktionen bereitstellen. Ausgehend von der Praxis führt Wang Shuai Sie nach der Erkundung des Prinzips schwach typisierter Variablen weiter zur Erläuterung einiger gemeinsamer Teile des PHP-Kernels. Dieses Problem ist ein tiefgreifendes Verständnis von SAPI.

SAPI ist die Abkürzung für Server Application Programming Interface. PHP stellt über SAPI eine Reihe von Schnittstellen für die Dateninteraktion zwischen Anwendungen und dem PHP-Kernel bereit.

Um es einfach auszudrücken: Genau wie die Eingabe und Ausgabe einer Funktion führen wir einen Teil des PHP-Codes über die Linux-Befehlszeile aus. Das Wesentliche ist, dass die Linux-Shell eine Reihe von Parametern über die SAPI von PHP übergibt . Nachdem die Zend-Engine es ausgeführt hat, kehrt sie zur Shell zurück, dem von der Shell angezeigten Prozess. In ähnlicher Weise wird PHP über Apache aufgerufen und Daten werden über den Webserver an SAPI übergeben. Nachdem die Zend-Engine ausgeführt wurde, werden sie an Apache zurückgegeben und Apache zeigt sie auf der Seite an.

Abbildung 1. PHP-Architekturdiagramm

PHP bietet viele Formen von Schnittstellen, einschließlich Apache, Apache2filter, Apache2handler, Caudium, CGI, CGI-FCGI, CLI, CLI-Server, Continuity , einbetten, isapi, litespeed, milter, nsapi, phttpd pi3web, roxen, thttpd, tux und webjames. Es gibt jedoch nur fünf häufig verwendete Formen: CLI/CGI (Befehlszeile), Multiprocess (Multiprozess), Multithreaded (Multithreaded), FastCGI und Embedded (eingebettet).

PHP bietet eine Funktion zum Anzeigen des aktuellen SAPI-Schnittstellentyps:

string php_sapi_name ( void )

PHP läuft und lädt

Egal welche SAPI verwendet wird, vor und nach der Ausführung durch PHP Skript, enthält eine Reihe von Ereignissen: Init (MINT) und Herunterfahren (MSHUTDOWN) des Moduls, Init (RINT) und Herunterfahren (RSHUTDOWN) der Anforderung. Die erste Phase ist die PHP-Modulinitialisierungsphase (MINT), in der erweiterte interne Variablen initialisiert, Ressourcen zugewiesen und Ressourcenprozessoren registriert werden können. Dieser Prozess wird nur einmal während des gesamten PHP-Instanzlebenszyklus ausgeführt.

Was ist ein PHP-Modul? Über das PHP-Architekturdiagramm oben können Sie die Funktion get_loaded_extensions in PHP verwenden, um alle kompilierten und geladenen Module/Erweiterungen anzuzeigen, was php -m im CLI-Modus entspricht.

Nehmen Sie den Quellcode der Memcached-Erweiterung von PHP:

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

Die zweite Phase ist die Anforderungsinitialisierungsphase (RINT). Nachdem das Modul initialisiert und aktiviert wurde, wird die PHP-Laufumgebung ausgeführt Rufen Sie die von allen Modulen registrierte RINT-Funktion auf, rufen Sie die Anforderungsinitialisierungsfunktion jeder Erweiterung auf, legen Sie bestimmte Umgebungsvariablen fest, weisen Sie Ressourcen zu oder führen Sie andere Aufgaben wie die Überwachung aus.

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

In der dritten Phase, nachdem die Anforderungsverarbeitung abgeschlossen ist, wird PHP_RSHUTDOWN_FUNCTION zum Recycling aufgerufen. Dies ist die Funktion zum Schließen der Anforderung jeder Erweiterung, um die endgültige Bereinigungsarbeit durchzuführen. Die Zend-Engine führt einen Bereinigungsprozess und eine Garbage Collection durch und setzt alle Variablen zurück, die bei früheren Anfragen verwendet wurden. Die Anfrage kann abgeschlossen werden, bis das Skript abgeschlossen ist, oder sie kann durch Aufrufen der Funktion die() oder exit() abgeschlossen werden.

In der vierten Phase, wenn der PHP-Lebenszyklus endet, recycelt PHP_MSHUTDOWN_FUNCTION das Modul. Dies gilt für die Shutdown-Funktion jedes erweiterten Moduls, mit der das eigene Kernel-Subsystem heruntergefahren wird.

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

Gemeinsame Betriebsmodi

Es gibt fünf gängige SAPI-Modi:

  • CLI- und CGI-Modus (Einzelprozessmodus)

  • Multiprozessmodus

  • Multithread-Modus

  • FastCGI-Modus

  • Eingebettet

1. CLI/CGI-Modus

Sowohl CLI als auch CGI gehören zum Einzelprozessmodus, und der Lebenszyklus von PHP wird in einem abgeschlossen Anfrage. Das heißt, jedes Mal, wenn ein PHP-Skript ausgeführt wird, werden die vier im zweiten Teil erwähnten INT- und Shutdown-Ereignisse ausgeführt.

Abbildung 2. CGI/CLI-Lebenszyklus

2. Multiprozessmodus (Multiprozess)

Der Multiprozessmodus kann PHP in den Webserver integrieren Wird unter Apache in den Prefork-MPM-Modus und das APXS-Modul kompiliert. Wenn Apache gestartet wird, werden viele untergeordnete Prozesse gegabelt, und jeder untergeordnete Prozess verfügt über einen eigenen unabhängigen Prozessadressraum.

Abbildung 3. Lebenszyklus im Multiprozessmodus

In einem untergeordneten Prozess besteht der Lebenszyklus von PHP darin, mehrere Anforderungen (RINT/RSHUTDOWN) auszuführen, nachdem MINT zum Starten aufgerufen wurde. MSHUTDOWN wird für die Recyclingphase erst aufgerufen, nachdem Apache heruntergefahren oder der Prozess beendet wurde.

Abbildung 4. Lebenszyklus von Multiprozessen

Im Multiprozessmodell läuft jeder Unterprozess unabhängig, ohne Code und Daten gemeinsam zu nutzen, sodass ein Unterprozess beendet wird. Das Beenden und Neustarten der Generierung hat keinen Einfluss auf die Stabilität anderer untergeordneter Prozesse.

3. Multithread-Modus (Multithreaded)

Apache2s Worker MPM verwendet ein Multithreading-Modell, das mehrere Threads unter einem Prozess erstellt und diese im selben Prozessadressraum ausführt.

Abbildung 5. Multi-Thread-Lebenszyklus

4. Der von uns verwendete Nginx+PHP-FPM verwendet den FastCGI-Modus Residenter Prozesstyp von CGI. Es ist nicht erforderlich, nach der Ausführung mehrere Prozesse zu forken. Es ist nicht erforderlich, für jede Anfrage MINT/MSHUTDOWN aufzurufen. PHP verwaltet und plant den Prozesspool von FastCGI über PHP-FPM. Nginx und PHP-FPM kommunizieren über lokale TCP-Sockets und Unix-Sockets.

Abbildung 6. Lebenszyklus des FastCGI-Modus

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内核--探究内存管理与缓存机制的图文详解

Das obige ist der detaillierte Inhalt vonTeilen von PHP-Kernel-SAPI-Erkundungsbeispielen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn