php 启动过程 - sapi MINIT 过程

时间:2023-03-09 23:38:24
php 启动过程 - sapi MINIT 过程

php 启动过程 - sapi MINIT 过程

sapi 概念

  • sapi 是 php 的应用编程接口, server 端接收请求通过 sapi 接口层交给 php 处理
  • 不同的 server 端底层实现不同, 相应的数据结构已经方法也有所不同, 但是对于 php 层面来说是一样的, 就是因为 sapi 层的存在
  • sapi 层对不同的 server 端进行了封装, 让 php 在处理时, 采用统一的处理方法, 并不感知底层到底是什么 server 端

sapi 生命周期前的启动过程 (以 apache2 为例)

  • apache 加载 php 模块

    • httpd.conf 配置

      • LoadModule php5_module modules/mod_php5.so
      • php5_module 是模块名称

      • apache 在启动加载模块时会根据模块名查找并加载模块, apache 模块文件必须是 "mod_" 开头的文件, 对于 php 来说, 则是 mod_php5.c

      • apache 的每个模块均为 module 结构体

        • AP_MODULE_DECLARE_DATA module php5_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, /* command apr_table_t */
          // php 模块注册钩子, 服务启动时注册
          php_ap2_register_hook /* register hooks */
          };
        • php_dir_cmds 为模块指令集, 当 apache 接收到指令后, 会遍历每个模块的指令集, 查看哪个模块能处理该指令, 进而调用相应处理函数

        • php_ap2_register_hook 为模块注册钩子, 当 apache 启动加载模块时调用

          • void php_ap2_register_hook(apr_pool_t *p)
            {
            ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
            // apache2 的注册钩子
            ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
            // apache2 处理请求时的钩子
            ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
            ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
            }
          • 定义位置在 sapi/apache2handler/sapi_apache2.c

          • ap_hook_pre_config, ap_hook_post_config, ap_hook_child_init 这三个钩子均在 apache 启动时调用, ap_hook_handler 钩子在每次处理请求时均会调用, 在 ap_hook_post_config 中启动 php

          • 调用 php_apache_server_startup

            • static int php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
              {
              // 省略
              if (apache2_php_ini_path_override) {
              apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
              }
              #ifdef ZTS
              // 启动线程安全资源管理
              tsrm_startup(1, 1, 0, NULL);
              #endif
              // sapi 启动
              sapi_startup(&apache2_sapi_module);
              //
              apache2_sapi_module.startup(&apache2_sapi_module);
              apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
              php_apache_add_version(pconf); return OK;
              }
  • sapi 启动

    • sapi 模块结构体

      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
      };
    • 调用 tsrm_startup (启动线程安全资源管理, 此处不做进一步展开, 在线程安全时单独展开)

    • 调用 sapi_startup (main/SAPI.c)

      SAPI_API void sapi_startup(sapi_module_struct *sf)
      {
      #ifdef ZEND_SIGNALS
      zend_signal_startup();
      #endif sf->ini_entries = NULL;
      sapi_module = *sf; #ifdef ZTS
      ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
      # ifdef PHP_WIN32
      _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
      # endif
      #else
      sapi_globals_ctor(&sapi_globals);
      #endif virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */ #ifdef PHP_WIN32
      tsrm_win32_startup();
      #endif reentrancy_startup();
      }
      • zend_signal_startup: 信号系统

      • sapi_globals_ctor: 创建 sapi 全局结构

        • static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
          {
          memset(sapi_globals, 0, sizeof(*sapi_globals));
          zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);
          php_setup_sapi_content_types(TSRMLS_C);
          }
        • typedef struct _sapi_globals_struct {
          // server 环境上下文
          void *server_context;
          // 请求信息
          sapi_request_info request_info;
          // 头信息
          sapi_headers_struct sapi_headers;
          // post 字节数
          int read_post_bytes;
          // 是否发送头
          unsigned char headers_sent;
          struct stat global_stat;
          // 默认 mime 类型
          char *default_mimetype;
          // 默认字符集
          char *default_charset;
          // 上传文件
          HashTable *rfc1867_uploaded_files;
          // post 请求最大大小
          long post_max_size;
          int options;
          // sapi 是否已启动
          zend_bool sapi_started;
          // 请求时间
          double global_request_time;
          // 已知的 post 的 content_type
          HashTable known_post_content_types;
          zval *callback_func;
          zend_fcall_info_cache fci_cache;
          zend_bool callback_run;
          } sapi_globals_struct;
        • 调用 php_setup_sapi_contents_types, 设置 post 请求相关的参数和处理方法

          int php_setup_sapi_content_types(TSRMLS_D)
          {
          sapi_register_post_entries(php_post_entries TSRMLS_CC); return SUCCESS;
          }
          static sapi_post_entry php_post_entries[] = {
          { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_std_post_handler },
          { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, NULL, rfc1867_post_handler },
          { NULL, 0, NULL, NULL }
          };
          struct _sapi_post_entry {
          char *content_type;
          uint content_type_len;
          void (*post_reader)(TSRMLS_D);
          void (*post_handler)(char *content_type_dup, void *arg TSRMLS_DC);
          };
          • 调用 sapi_register_post_entries

            • SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries TSRMLS_DC)
              {
              sapi_post_entry *p=post_entries; while (p->content_type) {
              if (sapi_register_post_entry(p TSRMLS_CC) == FAILURE) {
              return FAILURE;
              }
              p++;
              }
              return SUCCESS;
              }
            • SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
              {
              // 若 sapi 已启动并且正在执行当中, 不允许注册 post 结构体
              if (SG(sapi_started) && EG(in_execution)) {
              return FAILURE;
              }
              return zend_hash_add(&SG(known_post_content_types),
              post_entry->content_type, post_entry->content_type_len+1,
              (void *) post_entry, sizeof(sapi_post_entry), NULL);
              }
    • 调用 apache2_sapi_module.startup

      static int php_apache2_startup(sapi_module_struct *sapi_module)
      {
      if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
      return FAILURE;
      }
      return SUCCESS;
      }
      • php_apache_module 参数是 zend 引擎封装的模块结构

        • zend_module_entry php_apache_module = {
          STANDARD_MODULE_HEADER,
          "apache2handler",
          apache_functions,
          PHP_MINIT(apache), // 扩展为 zm_startup_##module
          PHP_MSHUTDOWN(apache), // 扩展为 zm_shutdown_##module
          NULL,
          NULL,
          PHP_MINFO(apache), // 扩展为 zm_info_##module
          NULL,
          STANDARD_MODULE_PROPERTIES
          };
        • struct _zend_module_entry {
          unsigned short size;
          unsigned int zend_api;
          unsigned char zend_debug;
          unsigned char zts;
          const struct _zend_ini_entry *ini_entry;
          const struct _zend_module_dep *deps;
          // 模块名称
          const char *name;
          const struct _zend_function_entry *functions;
          // 模块启动时调用的函数
          int (*module_startup_func)(INIT_FUNC_ARGS);
          // 模块关闭时调用的函数
          int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
          // 请求开始时调用的函数
          int (*request_startup_func)(INIT_FUNC_ARGS);
          // 请求结束时调用的函数
          int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
          // 模块信息函数
          void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
          // 版本
          const char *version;
          size_t globals_size;
          #ifdef ZTS
          ts_rsrc_id* globals_id_ptr;
          #else
          void* globals_ptr;
          #endif
          void (*globals_ctor)(void *global TSRMLS_DC);
          void (*globals_dtor)(void *global TSRMLS_DC);
          int (*post_deactivate_func)(void);
          int module_started;
          unsigned char type;
          void *handle;
          int module_number;
          const char *build_id;
          };
      • 调用 php_module_startup (main/main.c)

        • int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
          {
          zend_utility_functions zuf;
          zend_utility_values zuv;
          int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */
          char *php_os;
          zend_module_entry *module; // 省略 ... module_shutdown = 0;
          module_startup = 1;
          // 初始化空请求
          sapi_initialize_empty_request(TSRMLS_C);
          // sapi 激活
          sapi_activate(TSRMLS_C); if (module_initialized) {
          return SUCCESS;
          } sapi_module = *sf;
          // php 输出功能启动
          php_output_startup();
          // 设置 zend 引擎使用的函数
          zuf.error_function = php_error_cb;
          zuf.printf_function = php_printf;
          zuf.write_function = php_output_wrapper;
          zuf.fopen_function = php_fopen_wrapper_for_zend;
          zuf.message_handler = php_message_handler_for_zend;
          zuf.block_interruptions = sapi_module.block_interruptions;
          zuf.unblock_interruptions = sapi_module.unblock_interruptions;
          zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
          zuf.ticks_function = php_run_ticks;
          zuf.on_timeout = php_on_timeout;
          zuf.stream_open_function = php_stream_open_for_zend;
          zuf.vspprintf_function = vspprintf;
          zuf.getenv_function = sapi_getenv;
          zuf.resolve_path_function = php_resolve_path_for_zend;
          // zend 引擎启动
          zend_startup(&zuf, NULL TSRMLS_CC); // 省略 ... // 创建垃圾回收机制全局结构体
          gc_globals_ctor(TSRMLS_C); // 省略 ... // 设置全局结构体的一些值
          EG(bailout) = NULL;
          EG(error_reporting) = E_ALL & ~E_NOTICE;
          EG(active_symbol_table) = NULL;
          PG(header_is_being_sent) = 0;
          SG(request_info).headers_only = 0;
          SG(request_info).argv0 = NULL;
          SG(request_info).argc=0;
          SG(request_info).argv=(char **)NULL;
          PG(connection_status) = PHP_CONNECTION_NORMAL;
          PG(during_request_startup) = 0;
          PG(last_error_message) = NULL;
          PG(last_error_file) = NULL;
          PG(last_error_lineno) = 0;
          EG(error_handling) = EH_NORMAL;
          EG(exception_class) = NULL;
          PG(disable_functions) = NULL;
          PG(disable_classes) = NULL;
          EG(exception) = NULL;
          EG(objects_store).object_buckets = NULL; // 省略 ... // 注册一些常量
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
          #ifdef ZTS
          REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 1, CONST_PERSISTENT | CONST_CS);
          #else
          REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 0, CONST_PERSISTENT | CONST_CS);
          #endif
          REGISTER_MAIN_LONG_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_SAPI", sapi_module.name, strlen(sapi_module.name), CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("DEFAULT_INCLUDE_PATH", PHP_INCLUDE_PATH, sizeof(PHP_INCLUDE_PATH)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PEAR_INSTALL_DIR", PEAR_INSTALLDIR, sizeof(PEAR_INSTALLDIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PEAR_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_PREFIX", PHP_PREFIX, sizeof(PHP_PREFIX)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINDIR", PHP_BINDIR, sizeof(PHP_BINDIR)-1, CONST_PERSISTENT | CONST_CS);
          #ifndef PHP_WIN32
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_MANDIR", PHP_MANDIR, sizeof(PHP_MANDIR)-1, CONST_PERSISTENT | CONST_CS);
          #endif
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_LIBDIR", PHP_LIBDIR, sizeof(PHP_LIBDIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_DATADIR", PHP_DATADIR, sizeof(PHP_DATADIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_SYSCONFDIR", PHP_SYSCONFDIR, sizeof(PHP_SYSCONFDIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_LOCALSTATEDIR", PHP_LOCALSTATEDIR, sizeof(PHP_LOCALSTATEDIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS); #ifdef PHP_WIN32
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR", EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MINOR", EG(windows_version_info).dwMinorVersion, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_BUILD", EG(windows_version_info).dwBuildNumber, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PLATFORM", EG(windows_version_info).dwPlatformId, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MAJOR", EG(windows_version_info).wServicePackMajor, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MINOR", EG(windows_version_info).wServicePackMinor, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SUITEMASK", EG(windows_version_info).wSuiteMask, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PRODUCTTYPE", EG(windows_version_info).wProductType, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_DOMAIN_CONTROLLER", VER_NT_DOMAIN_CONTROLLER, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_SERVER", VER_NT_SERVER, CONST_PERSISTENT | CONST_CS);
          REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
          #endif
          // php 命令初始化, 主要是设置 php 命令路径
          php_binary_init(TSRMLS_C);
          if (PG(php_binary)) {
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS);
          } else {
          REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS);
          }
          // 注册 php 输出功能相关的一些常量
          php_output_register_constants(TSRMLS_C);
          // 注册 php 上传功能相关的一些常量
          php_rfc1867_register_constants(TSRMLS_C); // 读取 php.ini 配置
          if (php_init_config(TSRMLS_C) == FAILURE) {
          return FAILURE;
          } // 将 php.ini 文件读取的配置注册成 ini_entry
          REGISTER_INI_ENTRIES(); // 注册 zend 引擎的 ini_entry
          zend_register_standard_ini_entries(TSRMLS_C); /* Disable realpath cache if an open_basedir is set */
          if (PG(open_basedir) && *PG(open_basedir)) {
          CWDG(realpath_cache_size_limit) = 0;
          } // php 流的初始化
          if (php_init_stream_wrappers(module_number TSRMLS_CC) == FAILURE) {
          php_printf("PHP: Unable to initialize stream url wrappers.\n");
          return FAILURE;
          } zuv.html_errors = 1;
          zuv.import_use_extension = ".php";
          // 注册超全局数组 $_GET, $_POST, $_COOKIE, ...
          php_startup_auto_globals(TSRMLS_C);
          zend_set_utility_values(&zuv);
          // 启动 sapi 的处理请求功能, 设置一些处理函数
          php_startup_sapi_content_types(TSRMLS_C); // 注册 php 内置扩展 (module_registry)
          if (php_register_internal_extensions_func(TSRMLS_C) == FAILURE) {
          php_printf("Unable to start builtin modules\n");
          return FAILURE;
          }
          // 注册附加扩展 (module_registry)
          php_register_extensions_bc(additional_modules, num_additional_modules TSRMLS_CC);
          // 注册 php.ini 文件设置的扩展 (zend_extensions)
          php_ini_register_extensions(TSRMLS_C); // 启动各模块 (module_registry), 调用各模块的 startup 方法
          zend_startup_modules(TSRMLS_C);
          // 启动各扩展 (zend_extentions), 调用各扩展的 startup 方法
          zend_startup_extensions();
          // 统计各模块的启动情况
          zend_collect_module_handlers(TSRMLS_C); /* register additional functions */
          if (sapi_module.additional_functions) {
          if (zend_hash_find(&module_registry, "standard", sizeof("standard"), (void**)&module)==SUCCESS) {
          EG(current_module) = module;
          zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
          EG(current_module) = NULL;
          }
          } // 禁用函数
          php_disable_functions(TSRMLS_C);
          // 禁用类
          php_disable_classes(TSRMLS_C); // 省略 ... // sapi
          sapi_deactivate(TSRMLS_C);
          module_startup = 0;
          // 关闭内存管理
          shutdown_memory_manager(1, 0 TSRMLS_CC);
          zend_interned_strings_snapshot(TSRMLS_C); /* we're done */
          return retval;
          }
        • 初始化 zend 引擎使用的一些函数和值

        • 初始化 sapi_global 的一些值 (通过初始化空请求, sapi 激活)

        • 初始化全局结构体的一些值

        • zend 引擎启动

        • 设置一些常量

        • 加载 php.ini 配置

        • 注册各子模块和扩展

        • 启动各子模块和扩展

        • 禁用函数和类

    • 调用 apr_pool_cleanup_register

sapi 生命周期

  • MINIT

    若不细致区分 sapi 启动前的准备工作与启动过程, 上面的部分均可以看成是 sapi MINIT 过程
    若细致区分, sapi 启动前的准备工作是在注册 php 内置扩展之前的部分; 之后的部分为 MINIT 过程
  • RINIT

  • RSHUTDOWN

  • MSHUTDOWN

对于以上内容的更细致的点, 比如线程资源安全, zend 引擎启动, 全局结构体, php.ini 如何加载配置等等等等, 由于篇幅问题, 不在此赘述, 内容太多消化不了, 会在后续一个一个详细剖析, 本节仅涉及到 sapi 生命周期当中的 MINIT 过程