我们知道定义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;
- }