Nous savons tous que PHP doit s'exécuter sur un serveur WEB spécifique, tel que Nginx, Apache, etc., mais comment PHP démarre-t-il, comment s'exécute-t-il sur le serveur et puis les deux Comment interagir ?
Tutoriels recommandés : Tutoriel vidéo php
1. 🎜>
En prenant le serveur Apache comme exemple, voyons comment le serveur démarre PHP et appelle les méthodes en PHP. Lorsque le serveur Apache démarre et exécute PHP, il est généralement intégré via le module mod_php7 (s'il s'agit du php5. 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 */ };
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); }
#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \ MODULE_MAGIC_NUMBER_MINOR, \ -1, \ __FILE__, \ NULL, \ NULL, \ MODULE_MAGIC_COOKIE, \ NULL /* rewrite args spot */
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} };
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); }
2. PHP appelle l'interface du serveur WEB
Avant de parler de ce problème, nous devons comprendre ce qu'est SAPI. SAPI est en fait un accord commun observé entre la couche d'abstraction du serveur et la couche d'abstraction du serveur. Cela peut être facilement compris. Lorsque PHP a besoin d'appeler une méthode sur le serveur, comme vider le cache, la méthode d'implémentation pour vider le cache est implémentée. sur le serveur, et la couche PHP ne le sait pas du tout. Comment appeler cette méthode sur le serveur ? À ce stade, les deux parties doivent conclure un accord, puis le serveur fournit un ensemble d'interfaces convenues à PHP. Nous appelons ces accords communs avec la couche d'abstraction du serveur l'interface SAPI. La question est, pour le serveur Apache, nous pouvons fournir un ensemble de SAPI, mais si un autre serveur ou autre "tiers" vient la prochaine fois, alors devons-nous également leur fournir un ensemble de SAPI ? Qu'en est-il d'un SAPI séparé ? Nos développeurs PHP intelligents ont dû y penser, c'est-à-dire fournir un ensemble commun d'interfaces SAPI pour tous les "tiers", mais vous pouvez vous demander si les nouveaux "tiers" ont besoin de l'interface, votre SAPI commun n'en a pas. Oui , que dois-je faire ? Je crois comprendre qu'il faut ajouter de nouvelles fonctions à l'interface SAPI générale de PHP. Ceci n'est que mon opinion personnelle. La structure générale de SAPI est la suivante (chemin du code source : 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 //... };
Il y a beaucoup de variables dans cette structure, donc je ne les listerai pas une par une. Expliquons brièvement les variables à l'intérieur : la fonction de démarrage est appelée lorsque SAPI est initialisé, la fonction d'arrêt est utilisée pour libérer la structure de données SAPI. et mémoire, etc., read_cookie Il est appelé lorsque SAPI est activé, puis attribue la valeur obtenue par cette fonction à SG(request_info).cookie_data. Alors pour le SAPI général fourni par PHP, comment le serveur Apache personnalise-t-il sa propre interface ? La structure spécifique est la suivante (le chemin du code source est 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 };
上述源码目录php/sapi/apache2handler/中,目录php/sapi下面放的都是通过SAPI调用的“第三方”,该目录结构如下图所示,目录php/sapi/apache2handler中都是与PHP交互的接口,sapi_apache2.c是PHP与Apache约定的SAPI接口文件。
看到这里,大家应该基本清楚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的接口,是不是很简单呢:)
3.后记
这篇博文是我参考《深入理解PHP内核》一书总结的,参考的内容为第二章第二节“SAPI概述”,不过我感觉该书中这部分内容讲的有点绕,我重新编排了,然后提取了里面的重点,并加入个人见解,如果在该文中有哪些讲的不对的地方,希望能帮我指出来,大家共同提高哈,谢谢!
原文地址:https://blog.csdn.net/lml200701158/article/details/52267573
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!