扩展是什么?
如果你用过PHP,那么你肯定用到过扩展。除了少数例外,每个用户空间的函数都被组织在不同的扩展中。这些函数中的很多够成了
standard扩展-总数超过400。PHP本身带有86个扩展(原文写就之时-译注),平均每个含有大约30个函数。数学操作方面大约有2500个函数。似乎这还不够,
PECL仓库另外提供了超过100个扩展,而且互联网上可以找到更多。
“除了扩展中的函数,还有什么?”我听到了你的疑问。“扩展的
里面是什么?PHP的‘核心’是什么?”
PHP的核心由两部分组成。最底层是
Zend引擎(ZE)。ZE把人类易读的脚本解析成机器可读的符号,然后在进程空间内执行这些符号。ZE也处理内存管理、变量作用域及调度程序调用。另一部分是
PHP内核,它绑定了
SAPI层(Server Application Programming Interface,通常涉及主机环境,如Apache,IIS,CLI,CGI等),并处理与它的通信。它同时对safe_mode和open_basedir的检测提供一致的控制层,就像流层将fopen()、fread()和fwrite()等用户空间的函数与文件和网络I/O联系起来一样。
生存周期
当给定的SAPI启动时,例如在对/usr/local/apache/bin/apachectl start的响应中,PHP由初始化其内核子系统开始。在接近启动例程的末尾,它加载每个扩展的代码并调用其
模块初始化例程(MINIT)。这使得每个扩展可以初始化内部变量、分配资源、注册资源处理器,以及向ZE注册自己的函数,以便于脚本调用这其中的函数时候ZE知道执行哪些代码。
接下来,PHP等待SAPI层请求要处理的页面。对于CGI或CLI等SAPI,这将立刻发生且只发生一次。对于Apache、IIS或其他成熟的web服务器SAPI,每次远程用户请求页面时都将发生,因此重复很多次,也可能并发。不管请求如何产生,PHP开始于要求ZE建立脚本的运行环境,然后调用每个扩展的
请求初始化(RINIT)函数。RINIT使得扩展有机会设定特定的环境变量,根据请求分配资源,或者执行其他任务,如审核。 session扩展中有个RINIT作用的典型示例,如果启用了session.auto_start选项,RINIT将自动触发用户空间的session_start()函数以及预组装$_SESSION变量。
一旦请求被初始化了,ZE开始接管控制权,将PHP脚本翻译成
符号,最终形成
操作码并逐步运行之。如任一操作码需要调用扩展的函数,ZE将会把参数绑定到该函数,并且临时交出控制权直到函数运行结束。
脚本运行结束后,PHP调用每个扩展的
请求关闭(RSHUTDOWN)函数以执行最后的清理工作(如将session变量存入磁盘)。接下来,ZE执行清理过程(
垃圾收集)-有效地对之前的请求期间用到的每个变量执行unset()。
一旦完成,PHP继续等待SAPI的其他文档请求或者是关闭信号。对于CGI和CLI等SAPI,
没有“下一个请求”,所以SAPI立刻开始关闭。关闭期间,PHP再次遍历每个扩展,调用其
模块关闭(MSHUTDOWN)函数,并最终关闭自己的内核子系统。
这个过程乍听起来很让人气馁,但是一旦你深入一个运转的扩展,你会逐渐开始了解它。