鸟哥的博客提到了SAPI,我也来看下源码。
-------------
php架构图(图片出自http://stblog.baidu-tech.com/?p=763):
- 中间层(sapi)解耦隔离了web server和php
每个SAPI实现都是一个_sapi_module_struct 结构体:
在php源码目录下用 grep -r _sapi_module_struct 搜索到它的定义在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);
int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);
void (*flush)(void *server_context);
struct stat *(*get_stat)(TSRMLS_D);
char *(*getenv)(char *name, size_t name_len TSRMLS_DC);
void (*sapi_error)(int type, const char *error_msg, ...);
int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);
void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC);
int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC);
char *(*read_cookies)(TSRMLS_D);
void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
void (*log_message)(char *message TSRMLS_DC);
double (*get_request_time)(TSRMLS_D);
void (*terminate_process)(TSRMLS_D);
char *php_ini_path_override;
void (*block_interruptions)(void);
void (*unblock_interruptions)(void);
void (*default_post_reader)(TSRMLS_D);
void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC);
char *executable_location;
int php_ini_ignore;
int php_ini_ignore_cwd; /* don't look for php.ini in the current directory */
int (*get_fd)(int *fd TSRMLS_DC);
int (*force_http_10)(TSRMLS_D);
int (*get_target_uid)(uid_t * TSRMLS_DC);
int (*get_target_gid)(gid_t * TSRMLS_DC);
unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
void (*ini_defaults)(HashTable *configuration_hash);
int phpinfo_as_text;
char *ini_entries;
const zend_function_entry *additional_functions;
unsigned int (*input_filter_init)(TSRMLS_D);
};
下面,以cgi_sapi为例说明sapi的实现:
static sapi_module_struct cgi_sapi_module = {
"cgi-fcgi", /* name */
"CGI/FastCGI", /* pretty name */
php_cgi_startup, /* startup 当SAPI初始化时,首先会调用该函数 */
php_module_shutdown_wrapper, /* shutdown 关闭函数包装器,它用来释放所有的SAPI的数据结构、内存等*/
sapi_cgi_activate, /* activate 此函数会在每个请求开始时调用,它会再次初始化每个请求前的数据结构*/
sapi_cgi_deactivate, /* deactivate 此函数会在每个请求结束时调用,它用来确保所有的数据都,以及释放在activate中初始化的数据结构*/
sapi_cgi_ub_write, /* unbuffered write 不缓存的写操作(unbuffered write),它是用来将PHP的数据输出给客户端*/
sapi_cgi_flush, /* flush 刷新输出,在CLI模式下通过使用C语言的库函数fflush实现*/
NULL, /* get uid */
sapi_cgi_getenv, /* getenv */
php_error, /* error handler */
NULL, /* header handler */
sapi_cgi_send_headers, /* send headers handler 发送头部信息*/
NULL, /* send header handler */
sapi_cgi_read_post, /* read POST data 当请求的方法是POST时,程序会操作$_POST、$HTTP_RAW_POST_DATA等变量*/
sapi_cgi_read_cookies, /* read Cookies 在SAPI激活时,程序会调用此函数,并且将此函数获取的值赋值给SG(request_info).cookie_data*/
sapi_cgi_register_variables, /* register server variables */
sapi_cgi_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
参考:
1.http://stblog.baidu-tech.com/?p=763
2.http://www.laruence.com/2008/08/12/180.html
3.http://www.nowamagic.net/librarys/veda/detail/1292