PHP内核探索:再次探讨SAPI
2011-06-02 00:00
2011 查看
在PHP的生命周期的各个阶段,一些与服务相关的操作都是通过SAPI接口实现。 这些内置实现的物理位置在PHP源码的SAPI目录。这个目录存放了PHP对各个服务器抽象层的代码, 例如命令行程序的实现,Apache的mod_php模块实现以及fastcgi的实现等等。
在各个服务器抽象层之间遵守着相同的约定,这里我们称之为SAPI接口。 每个SAPI实现都是一个_sapi_module_struct结构体变量。(SAPI接口)。 在PHP的源码中,当需要调用服务器相关信息时,全部通过SAPI接口中对应方法调用实现, 而这对应的方法在各个服务器抽象层实现时都会有各自的实现。
下面是为SAPI的简单示意图:
以cgi模式和apache2服务器为例,它们的启动方法如下:
这里的cgi_sapi_module是sapi_module_struct结构体的静态变量。 它的startup方法指向php_cgi_startup函数指针。在这个结构体中除了startup函数指针,还有许多其它方法或字段。 其部分定义如下:
以上的这些结构在各服务器的接口实现中都有定义。如Apache2的定义:
目前PHP内置的很多SAPI实现都已不再维护或者变的有些非主流了,PHP社区目前正在考虑将一些SAPI移出代码库。 社区对很多功能的考虑是除非真的非常必要,或者某些功能已近非常通用了,否则就在PECL库中, 例如非常流行的APC缓存扩展将进入核心代码库中。
整个SAPI类似于一个面向对象中的模板方法模式的应用。 SAPI.c和SAPI.h文件所包含的一些函数就是模板方法模式中的抽象模板, 各个服务器对于sapi_module的定义及相关实现则是一个个具体的模板。
这样的结构在PHP的源码中有多处使用, 比如在PHP扩展开发中,每个扩展都需要定义一个zend_module_entry结构体。 这个结构体的作用与sapi_module_struct结构体类似,都是一个类似模板方法模式的应用。 在PHP的生命周期中如果需要调用某个扩展,其调用的方法都是zend_module_entry结构体中指定的方法, 如在上一小节中提到的在执行各个扩展的请求初始化时,都是统一调用request_startup_func方法, 而在每个扩展的定义时,都通过宏PHP_RINIT指定request_startup_func对应的函数。 以VLD扩展为例:其请求初始化为PHP_RINIT(vld),与之对应在扩展中需要有这个函数的实现:
所以, 我们在写扩展时也需要实现扩展的这些接口,同样,当实现各服务器接口时也需要实现其对应的SAPI。
PHP内核探索:从SAPI接口开始
PHP内核探索:一次请求的开始与结束
PHP内核探索:一次请求生命周期
PHP内核探索:单进程SAPI生命周期
PHP内核探索:多进程/线程的SAPI生命周期
PHP内核探索:Zend引擎
PHP内核探索:再次探讨SAPI
PHP内核探索:Apache模块介绍
PHP内核探索:通过mod_php5支持PHP
PHP内核探索:Apache运行与钩子函数
PHP内核探索:嵌入式PHP
PHP内核探索:PHP的FastCGI
PHP内核探索:如何执行PHP脚本
PHP内核探索:PHP脚本的执行细节
PHP内核探索:操作码OpCode
PHP内核探索:PHP里的opcode
PHP内核探索:解释器的执行过程
PHP内核探索:变量概述
PHP内核探索:变量存储与类型
PHP内核探索:PHP中的哈希表
PHP内核探索:理解Zend里的哈希表
PHP内核探索:PHP哈希算法设计
PHP内核探索:翻译一篇HashTables文章
PHP内核探索:哈希碰撞攻击是什么?
PHP内核探索:常量的实现
PHP内核探索:变量的存储
PHP内核探索:变量的类型
PHP内核探索:变量的值操作
PHP内核探索:变量的创建
PHP内核探索:预定义变量
PHP内核探索:变量的检索
PHP内核探索:变量的类型转换
PHP内核探索:弱类型变量的实现
PHP内核探索:静态变量的实现
PHP内核探索:变量类型提示
PHP内核探索:变量的生命周期
PHP内核探索:变量赋值与销毁
PHP内核探索:变量作用域
PHP内核探索:诡异的变量名
PHP内核探索:变量的value和type存储
PHP内核探索:全局变量Global
PHP内核探索:变量类型的转换
PHP内核探索:内存管理开篇
PHP内核探索:Zend内存管理器
PHP内核探索:PHP的内存管理
PHP内核探索:内存的申请与销毁
PHP内核探索:引用计数与写时复制
PHP内核探索:PHP5.3的垃圾回收机制
PHP内核探索:内存管理中的cache
PHP内核探索:写时复制COW机制
PHP内核探索:数组与链表
PHP内核探索:使用哈希表API
PHP内核探索:数组操作
PHP内核探索:数组源码分析
PHP内核探索:函数的分类
PHP内核探索:函数的内部结构
PHP内核探索:函数结构转换
PHP内核探索:定义函数的过程
PHP内核探索:函数的参数
PHP内核探索:zend_parse_parameters函数
PHP内核探索:函数返回值
PHP内核探索:形参return value
PHP内核探索:函数调用与执行
PHP内核探索:引用与函数执行
PHP内核探索:匿名函数及闭包
PHP内核探索:面向对象开篇
PHP内核探索:类的结构和实现
PHP内核探索:类的成员变量
PHP内核探索:类的成员方法
PHP内核探索:类的原型zend_class_entry
PHP内核探索:类的定义
PHP内核探索:访问控制
PHP内核探索:继承,多态与抽象类
PHP内核探索:魔术函数与延迟绑定
PHP内核探索:保留类与特殊类
PHP内核探索:对象
PHP内核探索:创建对象实例
PHP内核探索:对象属性读写
PHP内核探索:命名空间
PHP内核探索:定义接口
PHP内核探索:继承与实现接口
PHP内核探索:资源resource类型
PHP内核探索:Zend虚拟机
PHP内核探索:虚拟机的词法解析
PHP内核探索:虚拟机的语法分析
PHP内核探索:中间代码opcode的执行
PHP内核探索:代码的加密与解密
PHP内核探索:zend_execute的具体执行过程
PHP内核探索:变量的引用与计数规则
PHP内核探索:新垃圾回收机制说明
本文地址:https://www.geek-share.com/detail/2517944017.html,欢迎访问原出处。
在各个服务器抽象层之间遵守着相同的约定,这里我们称之为SAPI接口。 每个SAPI实现都是一个_sapi_module_struct结构体变量。(SAPI接口)。 在PHP的源码中,当需要调用服务器相关信息时,全部通过SAPI接口中对应方法调用实现, 而这对应的方法在各个服务器抽象层实现时都会有各自的实现。
下面是为SAPI的简单示意图:
以cgi模式和apache2服务器为例,它们的启动方法如下:
cgi_sapi_module.startup(&cgi_sapi_module) // cgi模式 cgi/cgi_main.c文件 apache2_sapi_module.startup(&apache2_sapi_module); // apache2服务器 apache2handler/sapi_apache2.c文件
这里的cgi_sapi_module是sapi_module_struct结构体的静态变量。 它的startup方法指向php_cgi_startup函数指针。在这个结构体中除了startup函数指针,还有许多其它方法或字段。 其部分定义如下:
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); // 不缓存的写操作(unbuffered write) void (*flush)(void *server_context); // flush struct stat *(*get_stat)(TSRMLS_D); // get uid char *(*getenv)(char *name, size_t name_len TSRMLS_DC); // getenv void (*sapi_error)(int type, const char *error_msg, ...); /* error handler */ int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC); /* header handler */ /* send headers handler */ int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC); void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC); /* send header handler */ int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC); /* read POST data */ char *(*read_cookies)(TSRMLS_D); /* read Cookies */ /* register server variables */ void (*register_server_variables)(zval *track_vars_array TSRMLS_DC); void (*log_message)(char *message); /* Log message */ time_t (*get_request_time)(TSRMLS_D); /* Request Time */ void (*terminate_process)(TSRMLS_D); /* Child Terminate */ char *php_ini_path_override; // 覆盖的ini路径 ... ... };
以上的这些结构在各服务器的接口实现中都有定义。如Apache2的定义:
static sapi_module_struct apache2_sapi_module = { "apache2handler", "Apache 2.0 Handler", php_apache2_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ ... }
目前PHP内置的很多SAPI实现都已不再维护或者变的有些非主流了,PHP社区目前正在考虑将一些SAPI移出代码库。 社区对很多功能的考虑是除非真的非常必要,或者某些功能已近非常通用了,否则就在PECL库中, 例如非常流行的APC缓存扩展将进入核心代码库中。
整个SAPI类似于一个面向对象中的模板方法模式的应用。 SAPI.c和SAPI.h文件所包含的一些函数就是模板方法模式中的抽象模板, 各个服务器对于sapi_module的定义及相关实现则是一个个具体的模板。
这样的结构在PHP的源码中有多处使用, 比如在PHP扩展开发中,每个扩展都需要定义一个zend_module_entry结构体。 这个结构体的作用与sapi_module_struct结构体类似,都是一个类似模板方法模式的应用。 在PHP的生命周期中如果需要调用某个扩展,其调用的方法都是zend_module_entry结构体中指定的方法, 如在上一小节中提到的在执行各个扩展的请求初始化时,都是统一调用request_startup_func方法, 而在每个扩展的定义时,都通过宏PHP_RINIT指定request_startup_func对应的函数。 以VLD扩展为例:其请求初始化为PHP_RINIT(vld),与之对应在扩展中需要有这个函数的实现:
PHP_RINIT_FUNCTION(vld) { }
所以, 我们在写扩展时也需要实现扩展的这些接口,同样,当实现各服务器接口时也需要实现其对应的SAPI。
延伸阅读
此文章所在专题列表如下:PHP内核探索:从SAPI接口开始
PHP内核探索:一次请求的开始与结束
PHP内核探索:一次请求生命周期
PHP内核探索:单进程SAPI生命周期
PHP内核探索:多进程/线程的SAPI生命周期
PHP内核探索:Zend引擎
PHP内核探索:再次探讨SAPI
PHP内核探索:Apache模块介绍
PHP内核探索:通过mod_php5支持PHP
PHP内核探索:Apache运行与钩子函数
PHP内核探索:嵌入式PHP
PHP内核探索:PHP的FastCGI
PHP内核探索:如何执行PHP脚本
PHP内核探索:PHP脚本的执行细节
PHP内核探索:操作码OpCode
PHP内核探索:PHP里的opcode
PHP内核探索:解释器的执行过程
PHP内核探索:变量概述
PHP内核探索:变量存储与类型
PHP内核探索:PHP中的哈希表
PHP内核探索:理解Zend里的哈希表
PHP内核探索:PHP哈希算法设计
PHP内核探索:翻译一篇HashTables文章
PHP内核探索:哈希碰撞攻击是什么?
PHP内核探索:常量的实现
PHP内核探索:变量的存储
PHP内核探索:变量的类型
PHP内核探索:变量的值操作
PHP内核探索:变量的创建
PHP内核探索:预定义变量
PHP内核探索:变量的检索
PHP内核探索:变量的类型转换
PHP内核探索:弱类型变量的实现
PHP内核探索:静态变量的实现
PHP内核探索:变量类型提示
PHP内核探索:变量的生命周期
PHP内核探索:变量赋值与销毁
PHP内核探索:变量作用域
PHP内核探索:诡异的变量名
PHP内核探索:变量的value和type存储
PHP内核探索:全局变量Global
PHP内核探索:变量类型的转换
PHP内核探索:内存管理开篇
PHP内核探索:Zend内存管理器
PHP内核探索:PHP的内存管理
PHP内核探索:内存的申请与销毁
PHP内核探索:引用计数与写时复制
PHP内核探索:PHP5.3的垃圾回收机制
PHP内核探索:内存管理中的cache
PHP内核探索:写时复制COW机制
PHP内核探索:数组与链表
PHP内核探索:使用哈希表API
PHP内核探索:数组操作
PHP内核探索:数组源码分析
PHP内核探索:函数的分类
PHP内核探索:函数的内部结构
PHP内核探索:函数结构转换
PHP内核探索:定义函数的过程
PHP内核探索:函数的参数
PHP内核探索:zend_parse_parameters函数
PHP内核探索:函数返回值
PHP内核探索:形参return value
PHP内核探索:函数调用与执行
PHP内核探索:引用与函数执行
PHP内核探索:匿名函数及闭包
PHP内核探索:面向对象开篇
PHP内核探索:类的结构和实现
PHP内核探索:类的成员变量
PHP内核探索:类的成员方法
PHP内核探索:类的原型zend_class_entry
PHP内核探索:类的定义
PHP内核探索:访问控制
PHP内核探索:继承,多态与抽象类
PHP内核探索:魔术函数与延迟绑定
PHP内核探索:保留类与特殊类
PHP内核探索:对象
PHP内核探索:创建对象实例
PHP内核探索:对象属性读写
PHP内核探索:命名空间
PHP内核探索:定义接口
PHP内核探索:继承与实现接口
PHP内核探索:资源resource类型
PHP内核探索:Zend虚拟机
PHP内核探索:虚拟机的词法解析
PHP内核探索:虚拟机的语法分析
PHP内核探索:中间代码opcode的执行
PHP内核探索:代码的加密与解密
PHP内核探索:zend_execute的具体执行过程
PHP内核探索:变量的引用与计数规则
PHP内核探索:新垃圾回收机制说明
本文地址:https://www.geek-share.com/detail/2517944017.html,欢迎访问原出处。
相关文章推荐
- 7.PHP内核探索:再次探讨SAPI
- PHP内核探索 —— 再次探讨SAPI
- 8.PHP内核探索:再次探讨SAPI
- PHP内核探索:再次探讨SAPI
- 108 内核探索 --php扩展、zend引擎、sapi
- 5.PHP内核探索:多进程/线程的SAPI生命周期
- PHP内核探索:从SAPI接口开始
- PHP内核探索:单进程SAPI生命周期
- 1.PHP内核探索:从SAPI接口开始
- PHP内核探索:单进程SAPI生命周期
- PHP内核探索:多进程/线程的SAPI生命周期
- PHP内核探索:多进程/线程的SAPI生命周期
- 5.PHP内核探索:多进程/线程的SAPI生命周期
- 1.PHP内核探索:从SAPI接口开始
- PHP内核探索:从SAPI接口开始
- PHP内核探索 —— 从SAPI接口开始
- 1.PHP内核探索:从SAPI接口开始
- 4.PHP内核探索:单进程SAPI生命周期
- 4.PHP内核探索:单进程SAPI生命周期
- PHP内核探索:从SAPI接口开始