Heim >Backend-Entwicklung >PHP-Problem >Vertiefte Kenntnisse der PHP-Prinzipien und der Interaktion zwischen PHP- und WEB-Servern
Jeder weiß, dass PHP auf einem bestimmten WEB-Server wie Nginx, Apache usw. ausgeführt werden muss, aber wie startet PHP, wie läuft es auf dem Server und wie interagieren die beiden?
1. Der WEB-Server ruft die PHP-Schnittstelle auf
Am Beispiel des Apache-Servers sehen wir uns an, wie der Server PHP startet und Methoden in PHP aufruft. Wenn der Apache-Server PHP startet und ausführt, wird es normalerweise über das mod_php7
-Modul integriert (wenn es sich um die php5.*-Version handelt, ist es das mod_php5
-Modul, und der Modulsuffixname hängt von der PHP-Version ab). Die Struktur von mod_php7 ist wie folgt (der Quellcodepfad ist php/sapi/apache2handler/mod_php7.c):
AP_MODULE_DECLARE_DATA module php7_module = { STANDARD20_MODULE_STUFF,/* 宏,包括版本,版本,模块索引,模块名,下个模块指针等信息 */ create_php_config, /* create per-directory config structure */ merge_php_config, /* merge per-directory config structures */ NULL, /* create per-server config structure */ NULL, /* merge per-server config structures */ php_dir_cmds, /* 模块定义的所有指令 */ php_ap2_register_hook /* register hooks */ };
Wenn Apache eine Methode in PHP aufrufen muss, muss er die Anfrage nur über PHP an PHP kommunizieren Das Modul mod_php7 und die PHP-Schicht geben die Daten nach der Verarbeitung an Apache zurück. Der gesamte Prozess ist beendet (bitte hinzufügen: Wenn der Apache-Server PHP startet, gibt es tatsächlich zwei Lademethoden, eine ist statisches Laden und die andere ist dynamisches Laden Die gerade besprochene Methode zum Laden von mod_php5-Modulen kann als statisches Laden verstanden werden. Das heißt, Sie müssen den Apache-Server neu starten, um PHP zu laden Server durch Senden von Signalen, um den Zweck des PHP-Starts zu erreichen. Vor dem dynamischen Laden müssen Sie jedoch das geladene Modul in eine dynamische Linkbibliothek kompilieren und es dann in der Konfigurationsdatei des Servers konfigurieren. Die Modellstruktur von Apache in PHP wurde oben angegeben. Die entsprechende Modulstruktur im Apache-Server ist unten angegeben (der Quellcode befindet sich in Apache, derselbe unten):
struct module_struct { int version; int minor_version; int module_index; const char *name; void *dynamic_load_handle; struct module_struct *next; unsigned long magic; void (*rewrite_args) (process_rec *process); void *(*create_dir_config) (apr_pool_t *p, char *dir); void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf); void *(*create_server_config) (apr_pool_t *p, server_rec *s); void *(*merge_server_config) (apr_pool_t *p, void *base_conf, void *new_conf); const command_rec *cmds; void (*register_hooks) (apr_pool_t *p); }
Sie können php7_module sehen und module_struct Es gibt immer noch große Unterschiede, aber wenn Sie sehen, wie das Makro php7_module.STANDARD20_MODULE_STUFF definiert ist, denken Sie vielleicht, dass die beiden Strukturen sehr ähnlich sind. Tatsächlich definiert dieses Makro die ersten 8 Parameter in module_struct, die als definiert sind folgt:
#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \ MODULE_MAGIC_NUMBER_MINOR, \ -1, \ __FILE__, \ NULL, \ NULL, \ MODULE_MAGIC_COOKIE, \ NULL /* rewrite args spot */
Dann definiert php7_module.php_dir_cmds alle Befehlssätze des Moduls. Die spezifische Definition lautet wie folgt (der Codepfad ist php/sapi/apache2handler/apache_config.c):
const command_rec php_dir_cmds[] = { AP_INIT_TAKE2("php_value", php_apache_value_handler, NULL, OR_OPTIONS, "PHP Value Modifier"), AP_INIT_TAKE2("php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, "PHP Flag Modifier"), AP_INIT_TAKE2("php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Value Modifier (Admin) "), AP_INIT_TAKE2("php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Flag Modifier (Admin)"), AP_INIT_TAKE1("PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, "Directory containing the php.ini file"), {NULL} };
Mit anderen Worten, die oben genannten fünf Anweisungen werden auch in der Datei apache_config.c bereitgestellt. Schließlich ist nur noch php7_module.php_ap2_register_hook übrig Codepfad ist php/sapi/apache2handler/mod_php7.c) :
void php_ap2_register_hook(apr_pool_t *p) { ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE); #ifdef ZEND_SIGNALS ap_hook_child_init(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE); #endif ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE); }
php7_module.php_ap2_register_hook-Funktion enthält 4 Hooks und entsprechende Verarbeitungsfunktionen. pre_config, pre_config, post_config und child_init sind Start-Hooks, die beim Server aufgerufen werden Der Handler-Hook ist ein Anforderungs-Hook. Serveranforderungen sind Aufrufe. Über diese Hooks kann PHP über den Apache-Server gestartet werden.
Zu diesem Zeitpunkt müssen Sie bereits wissen, wie der WEB-Server PHP startet und die Methoden in PHP aufruft. Lassen Sie mich Ihnen nun erklären, wie PHP die WEB-Server-Schnittstelle aufruft.
2.PHP ruft die WEB-Server-Schnittstelle auf
Bevor wir über dieses Problem sprechen, müssen wir verstehen, was SAPI ist. SAPI ist eigentlich eine gemeinsame Vereinbarung zwischen der Serverabstraktionsschicht und der Serverabstraktionsschicht. Es ist leicht zu verstehen, dass PHP eine Methode zum Löschen des Caches implementiert im Server, und die PHP-Schicht weiß es überhaupt nicht. Wie rufe ich diese Methode im Server auf? Zu diesem Zeitpunkt müssen beide Parteien eine Vereinbarung treffen, und dann stellt der Server eine Reihe vereinbarter Schnittstellen für PHP bereit. Wir nennen diese gemeinsamen Vereinbarungen mit der Server-Abstraktionsschicht die SAPI-Schnittstelle.
Die Frage ist, dass wir für den Server Apache einen Satz SAPI bereitstellen können, aber wenn das nächste Mal ein anderer Server oder ein anderer „Dritter“ hinzukommt, müssen wir ihnen dann auch einen Satz SAPI bereitstellen ? Wie wäre es mit einer separaten SAPI? Unsere intelligenten PHP-Entwickler müssen darüber nachgedacht haben, nämlich einen gemeinsamen Satz von SAPI-Schnittstellen für alle „Dritten“ bereitzustellen. Sie fragen sich jedoch möglicherweise: Wenn die neuen „Dritten“ die Schnittstelle benötigen, benötigt Ihr gemeinsames SAPI dies nicht , was soll ich tun? Mein Verständnis ist, neue Funktionen zur allgemeinen SAPI-Schnittstelle von PHP hinzuzufügen. Dies ist nur meine persönliche Meinung. Die allgemeine SAPI-Struktur ist wie folgt (Quellcode-Pfad: php/main/SAPI.h):
struct _sapi_module_struct { char *name; // 名字 char *pretty_name; // 更好理解的名字 int (*startup)(struct _sapi_module_struct *sapi_module); // 启动函数 int (*shutdown)(struct _sapi_module_struct *sapi_module); // 关闭函数 int (*activate)(TSRMLS_D); // 激活 int (*deactivate)(TSRMLS_D); // 停用 void (*flush)(void *server_context); // flush char *(*read_cookies)(TSRMLS_D); //read Cookies //... };
Diese Struktur hat viele Variablen, daher werde ich sie nicht einzeln auflisten. Erklären wir kurz die darin enthaltenen Variablen: Die Startfunktion wird aufgerufen, wenn SAPI initialisiert wird, die Shutdown-Funktion wird zum Freigeben der SAPI-Daten verwendet Struktur und Speicher usw., read_cookie Es wird aufgerufen, wenn SAPI aktiviert ist, und weist dann den von dieser Funktion erhaltenen Wert SG(request_info).cookie_data zu. Wie passt der Apache-Server für das von PHP bereitgestellte allgemeine SAPI seine eigene Schnittstelle an? Die spezifische Struktur ist wie folgt (der Quellcodepfad ist php/sapi/apache2handler/sapi_apache2.c):
static sapi_module_struct apache2_sapi_module = { "apache2handler", "Apache 2.0 Handler", php_apache2_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ NULL, /* activate */ NULL, /* deactivate */ php_apache_sapi_ub_write, /* unbuffered write */ php_apache_sapi_flush, /* flush */ php_apache_sapi_get_stat, /* get uid */ php_apache_sapi_getenv, /* getenv */ php_error, /* error handler */ php_apache_sapi_header_handler, /* header handler */ php_apache_sapi_send_headers, /* send headers handler */ NULL, /* send header handler */ php_apache_sapi_read_post, /* read POST data */ php_apache_sapi_read_cookies, /* read Cookies */ php_apache_sapi_register_variables, php_apache_sapi_log_message, /* Log message */ php_apache_sapi_get_request_time, /* Request Time */ NULL, /* Child Terminate */ STANDARD_SAPI_MODULE_PROPERTIES };
Im obigen Quellcodeverzeichnis php/sapi/apache2handler/ wird alles unter dem Verzeichnis php/ abgelegt sapi wird über SAPI aufgerufen. Die Verzeichnisstruktur ist in der folgenden Abbildung dargestellt. Das Verzeichnis php/sapi/apache2handler enthält die Schnittstelle für die Interaktion mit PHP. sapi_apache2.c ist die zwischen PHP und Apache vereinbarte SAPI-Schnittstellendatei .
看到这里,大家应该基本清楚PHP层是怎样调用服务器层的接口,为了巩固上面的知识,下面举个栗子,即在Apache服务器环境下读取cookie:
SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
对于任意一个服务器在加载时,我们都会指定sapi_module,Apache的sapi_module是apache2_sapi_module,它的read_cookies方法的是php_apache_sapi_read_cookies函数,这样就实现PHP层调用Apache的接口,是不是很简单呢:)
更多相关问题可以访问PHP中文网相关教程:https://www.php.cn/course/list/29/type/2.html
Das obige ist der detaillierte Inhalt vonVertiefte Kenntnisse der PHP-Prinzipien und der Interaktion zwischen PHP- und WEB-Servern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!