我們知道定義SAPI之前,首先要定義sapi_module_struct這個結構,相看源碼:/soft/php-5.2.9/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 */
-
- STANDARD_SAPI_MODULE_PROPERTIES
- };
1,php_apache2_startup:當通過apache調用PHP時,這個函數會被調用。該函數定義如下,主要是對PHP進行初始化。
- 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;
- }
2,php_module_shutdown_wrapper :PHP的關閉函數。
3,PHP會在每個request的時候,處理一些初始化,資源分配的事務。這部分就是activate字段要定義的。
4,與activate的函數,就是deactiveate,它會提供一個handler, 用來處理收尾工作。
5,php_apache_sapi_ub_write:提供一個向Response數據寫的接口。
- static int
- php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
- {
- request_rec *r;
- php_struct *ctx;
-
- ctx = SG(server_context);
- r = ctx->r;
-
- if (ap_rwrite(str, str_length, r) < 0) {
- php_handle_aborted_connection();
- }
-
- return str_length; /* we always consume all the data passed to us. */
- }
6,php_apache_sapi_flush:提供給zend刷新緩存的句柄。
- static void
- php_apache_sapi_flush(void *server_context)
- {
- php_struct *ctx;
- request_rec *r;
- TSRMLS_FETCH();
-
- ctx = server_context;
-
- /* If we haven't registered a server_context yet,
- * then don't bother flushing. */
- if (!server_context) {
- return;
- }
-
- r = ctx->r;
-
- sapi_send_headers(TSRMLS_C);
-
- r->status = SG(sapi_headers).http_response_code;
- SG(headers_sent) = 1;
-
- if (ap_rflush(r) < 0 || r->connection->aborted) {
- php_handle_aborted_connection();
- }
- }
7,php_apache_sapi_get_stat:這部分用來讓Zend可以驗證一個要執行腳本文件的state,從而判斷文件是否據有執行權限等等。
- static struct stat*
- php_apache_sapi_get_stat(TSRMLS_D)
- {
- php_struct *ctx = SG(server_context);
-
- ctx->finfo.st_uid = ctx->r->finfo.user;
- ctx->finfo.st_gid = ctx->r->finfo.group;
- ctx->finfo.st_dev = ctx->r->finfo.device;
- ctx->finfo.st_ino = ctx->r->finfo.inode;
- #if defined(NETWARE) && defined(CLIB_STAT_PATCH)
- ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
- ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
- ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
- #else
- ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
- ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
- ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
- #endif
-
- ctx->finfo.st_size = ctx->r->finfo.size;
- ctx->finfo.st_nlink = ctx->r->finfo.nlink;
-
- return &ctx->finfo;
- }
8,php_apache_sapi_getenv:為Zend提供了一個根據name來查找環境變量的接口,當我們在腳本中調用getenv的時候,就會間接的調用這個句柄。
- static char *
- php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC)
- {
- php_struct *ctx = SG(server_context);
- const char *env_var;
-
- env_var = apr_table_get(ctx->r->subprocess_env, name);
-
- return (char *) env_var;
- }