Maison  >  Article  >  développement back-end  >  Compréhension approfondie de l'interaction PHP et serveur WEB

Compréhension approfondie de l'interaction PHP et serveur WEB

angryTom
angryTomavant
2019-08-21 17:55:052547parcourir

Compréhension approfondie de l'interaction PHP et serveur WEB

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

Lorsqu'Apache a besoin d'appeler une méthode en PHP, il suffit doit transmettre la requête à PHP via le module mod_php7. Une fois que la couche PHP a traité les données, elle renvoie les données à Apache. L'ensemble du processus est terminé (veuillez ajouter : lorsque le serveur Apache démarre PHP, il existe en fait deux méthodes de chargement. , l'un est un chargement statique et l'autre est un chargement dynamique. La méthode de chargement du module mod_php5 qui vient d'être évoquée peut être comprise comme un chargement statique, ce qui signifie qu'Apache doit être redémarré. Le serveur peut y charger PHP sans redémarrer. Il suffit de charger le module fixe PHP sur le serveur en envoyant des signaux pour atteindre l'objectif de démarrage de PHP. Cependant, avant le chargement dynamique, le module chargé doit être compilé dans une bibliothèque de liens dynamiques, puis configuré dans le serveur. fichier de configuration du serveur). La structure du modèle d'Apache en PHP a été donnée ci-dessus. La structure des modules correspondants dans le serveur Apache est donnée ci-dessous, comme suit (le code source est dans Apache, le même ci-dessous) :

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

Vous pouvez voir php7_module et module_struct Il y a encore de grandes différences, mais si vous voyez la façon dont la macro php7_module.STANDARD20_MODULE_STUFF est définie, vous penserez peut-être que les deux structures sont très similaires. En fait, cette macro définit les 8 premiers paramètres de module_struct, qui sont définis comme. suit :

#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \
    MODULE_MAGIC_NUMBER_MINOR, \
    -1, \
    __FILE__, \
    NULL, \
    NULL, \
    MODULE_MAGIC_COOKIE, \
    NULL /* rewrite args spot */

Ensuite, php7_module.php_dir_cmds définit tous les jeux d'instructions du module. La définition spécifique est la suivante (le chemin du code est 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}
};

C'est-à-dire la couche PHP uniquement. Les cinq instructions ci-dessus sont fournies à Apache. Le code source d'implémentation de chaque instruction est également dans le fichier apache_config.c. Enfin, il reste php7_module.php_ap2_register_hook. le chemin du code est 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);
}

La fonction php7_module.php_ap2_register_hook contient 4 hooks et les fonctions de traitement correspondantes pre_config, pre_config, post_config et child_init sont des hooks de démarrage, qui sont appelés lorsque le. Le serveur démarre. Le hook du gestionnaire est un hook de requête, ce qui signifie que les requêtes du serveur sont des appels, et grâce à ces hooks, PHP peut être démarré via le serveur Apache.

À ce stade, vous devez déjà savoir comment le serveur WEB démarre PHP et appelle les méthodes en PHP. Laissez-moi maintenant vous expliquer comment PHP appelle l'interface du serveur WEB.

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接口文件。 

20160821163330607 (1).jpg

  看到这里,大家应该基本清楚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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer