[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)

Posted Y4tacker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)相关的知识,希望对你有一定的参考价值。

写在前面

最近打了很多比赛,遇到了很多事,心也慢慢更静下来了

sapi_module_struct结构简单解读

我们以cli为例子,开始学习

入口

入口肯定是main函数了,首先定义一系列的变量,其中就有sapi_module_struct

main\\SAPI.h中有这个结构的定义

下面是各个参数的作用

struct _sapi_module_struct { 
    char *name; //名称,以这篇文章为例就是cli
    char *pretty_name; // 更易读的名字,比如cli对应的就是Command Line Interface,fpm-fcgi对应的为FPM/FastCGI

    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配置的函数指针,把ini配置信息存在HashTable中
    int phpinfo_as_text; //  是否输出phpinfo信息

    char *ini_entries; // 执行时附带的ini配置,可以使用php -d设置
    const zend_function_entry *additional_functions; // 每个SAPI模块特有的一些函数注册,比如cli的cli_get_process_title
    unsigned int (*input_filter_init)(void); 
};

Cli中给sapi_module_struct赋值


可以看到这里实现了很多方法,但有一些也是空实现的,以我们平时的经验,cli肯定是不会处理cookie的,看下图可以发现他只是空实现,其他的类似,比如处理header

参考文章

理解php内核中SAPI的作用
SAPIs

以上是关于[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)的主要内容,如果未能解决你的问题,请参考以下文章

[PHP内核]PHP内核学习------sapi_module_struct结构体解析(以cli为例)

[PHP内核]PHP内核学习------SAPI学习

[PHP内核]PHP内核学习------SAPI学习

PHP内核学习SAPI

php内核解析

PHP内核之旅-4.可变长度的字符串