[PHP内核]PHP内核学习------SAPI学习
Posted Y4tacker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[PHP内核]PHP内核学习------SAPI学习相关的知识,希望对你有一定的参考价值。
写在前面
新开一个坑,虽然未来php用的不多,但是学起来还是有点意思
SAPI学习
什么是SAPI
从php7内核剖析当中提到
PHP本身可以理解为是一个库函数,提供语言的编译与执行服务,它有标准的输入、输出,
而SAPI是PHP的接入层,它接收用户的请求,然后调用PHP内核提供的一些接口完成PHP脚
本的执行
从图中可以看出,各种应用都是通过对应的SAPI与php进行交互的,SAPI相当于一个接口,使得php的核心实现不用关心各个应用交互的细节。虽然通过Web服务器和命令行程序执行脚本看起来很不一样,实际上它们的工作流程是一样的。
而PHP中常用的SAPI有cli、php-fpm,cli是命令行下执行PHP脚本的实现
sapi_module_struct结构
简单注释
这个结构是sapi中最重要的数据结构。它的定义在main/SAPI.h中
struct _sapi_module_struct { // SAPI模块结构
char *name; // 应用层名称,比如cli,cgi等
char *pretty_name; // 应用层更易读的名字,比如cli对应的就是Command Line Interface
int (*startup)(struct _sapi_module_struct *sapi_module); // 当一个应用要调用php的时候,这个模块启动的时候会调用的函数
int (*shutdown)(struct _sapi_module_struct *sapi_module); // 当一个应用要调用php的时候,这个模块结束的时候会调用的函数
int (*activate)(void); // 在处理每个request的时候,激活需要调用的函数
int (*deactivate)(void); // 在处理完每个request的时候,收尾时候要调用的函数
size_t (*ub_write)(const char *str, size_t str_length); // 这个函数告诉php如何输出数据
void (*flush)(void *server_context); // 提供给php的刷新缓存的函数指针
zend_stat_t *(*get_stat)(void); // 用来判断要执行文件的权限,来判断是否有执行权限
char *(*getenv)(char *name, size_t name_len); // 获取环境变量的方法
void (*sapi_error)(int type, const char *error_msg, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); // 错误处理方法
int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers); // 这个函数会在我们调用header()的时候被调用
int (*send_headers)(sapi_headers_struct *sapi_headers); // 发送所有的header
void (*send_header)(sapi_header_struct *sapi_header, void *server_context); // 单独发送某一个header
size_t (*read_post)(char *buffer, size_t count_bytes); // 如何获取HTTP POST中的数据
char *(*read_cookies)(void); // 如何获取cookie中的数据
void (*register_server_variables)(zval *track_vars_array); // 这个函数可以给$_SERVER中获取变量
void (*log_message)(char *message, int syslog_type_int); // 输出错误信息函数
double (*get_request_time)(void); // 获取请求时间的函数
void (*terminate_process)(void); // TODO: 调用exit的时候调用的方法
char *php_ini_path_override; // PHP的ini文件被复写了所复写的地址
void (*default_post_reader)(void); // 这里和前面的read_post有个差别,read_post负责如何获取POST数据,而这里的函数负责如何解析POST数据
void (*treat_data)(int arg, char *str, zval *destArray); // 对数据进行处理,比如进行安全过滤等。 default_post_reader/tread_data/input_filter是三个能对输入进行过滤和处理的函数
char *executable_location; // 执行的地理位置
int php_ini_ignore; // 是否不使用任何ini配置文件,比如php -n 就将这个位置设置为1
int php_ini_ignore_cwd; // 不在当前路径寻找php.ini
int (*get_fd)(int *fd); // 获取执行文件的fd
int (*force_http_10)(void); // 强制使用http1.0
int (*get_target_uid)(uid_t *); // 获取执行程序的uid
int (*get_target_gid)(gid_t *); // 获取执行程序的gid
unsigned int (*input_filter)(int arg, char *var, char **val, size_t val_len, size_t *new_val_len); // 对输入进行过滤。比如将输入参数填充到自动全局变量$_GET, $_POST, $_COOKIE中
void (*ini_defaults)(HashTable *configuration_hash); // 默认的ini配置
int phpinfo_as_text; // 是否打印phpinfo信息
char *ini_entries; // 有没有附带的ini配置,比如使用php -d date.timezone=America/Adak,可以在命令行中设置时区
const zend_function_entry *additional_functions; // 每个SAPI模块特有的一些函数注册,比如cli的cli_get_process_title
unsigned int (*input_filter_init)(void); // TODO:
};
接下来我们看看不同模式下定义
cgi模式
cgi模式下,_sapi_module_struct的实例定义在cgi_main.c中。
static sapi_module_struct cgi_sapi_module = {
"cgi-fcgi", /* name */
"CGI/FastCGI", /* pretty name */
php_cgi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
sapi_cgi_ub_write, /* unbuffered write */
sapi_cgi_flush, /* flush */
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 */
sapi_cgi_read_cookies, /* read Cookies */
sapi_cgi_register_variables, /* register server variables */
sapi_cgi_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
cli 模式
在php_cli.c
static sapi_module_struct cli_sapi_module = {
"cli", /* name */
"Command Line Interface", /* pretty name */
php_cli_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
NULL, /* activate */
sapi_cli_deactivate, /* deactivate */
sapi_cli_ub_write, /* unbuffered write */
sapi_cli_flush, /* flush */
NULL, /* get uid */
NULL, /* getenv */
php_error, /* error handler */
sapi_cli_header_handler, /* header handler */
sapi_cli_send_headers, /* send headers handler */
sapi_cli_send_header, /* send header handler */
NULL, /* read POST data */
sapi_cli_read_cookies, /* read Cookies */
sapi_cli_register_variables, /* register server variables */
sapi_cli_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
fpm
static sapi_module_struct cgi_sapi_module = {
"fpm-fcgi", /* name */
"FPM/FastCGI", /* pretty name */
php_cgi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
sapi_cgibin_ub_write, /* unbuffered write */
sapi_cgibin_flush, /* flush */
NULL, /* get uid */
sapi_cgibin_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 */
sapi_cgi_read_cookies, /* read Cookies */
sapi_cgi_register_variables, /* register server variables */
sapi_cgi_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
简单总结
可以看见上面不同模式部分定义也不同,比如是否能获取cookie等,简单了解下即可
以上是关于[PHP内核]PHP内核学习------SAPI学习的主要内容,如果未能解决你的问题,请参考以下文章
[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)
[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)