PHPer 高手之路
  • Introduction
  • First Chapter
  • 基础
    • 数据类型和常量
    • 字符串
      • 字符编码
      • 字符编码相关编程
    • 引用变量
    • 运算符与错误控制符@
    • 流程控制与条件判断
      • foreach遍历中的引用
    • 函数
    • 文件及目录处理
  • PHP 数组
    • 基础
    • PHP数组操作
    • 输入流 php://input
    • PHP数组的内部实现
    • PHP数组和数据结构
    • 示例技巧
  • PHP文件编程
    • 文件系统
    • 基础
    • 实例技巧
    • PHP中XML处理
    • PHP中JSON处理
    • PHP中CSV处理
    • 大文件上传
  • 正则表达式
    • 基础
    • 正则的引擎
    • 表达式的优化
    • PHP中正则的使用
  • PHP 编码技巧
    • PHP编码习惯
    • PHP语法糖
    • PHP代码优化
    • PHP重点新特性
    • PHP编码规范
  • PHP选项和运行原理
    • PHP SAPI
    • PHP运行模式及安装方式
    • 附录:进程和线程的Q解
    • Apache下的MPM模式
    • Apache 与 Nginx
    • PHP的运行机制及原理
    • PHP垃圾回收机制
    • PHP配置选项
  • PHP安全
    • 跨站脚本攻击(XSS )
    • 跨站请求伪造(CRSF)
  • PHP 高级特性
    • 异常处理(Exceptions)
    • 代码复用(Trait)
    • 预定义接口(Predefined Interfaces)
    • 魔术方法(Magic Methods)
    • 回调函数、匿名函数&闭包
    • 命名空间(Namespaces)
    • 自动加载(Autoload)
    • 反射(Reflection)
    • 魔术常量(Magic constants)
    • 综合实例
  • 附录:关键词
  • 附录:资料
  • 代码的版本控制
    • SVN
    • Git
      • 疑难杂症
  • Linux
    • Linux原理与基础
    • 常见命令
    • Shell 编程
    • awk 与 sed
    • 命令笔记
  • HTTP 协议
    • 请求方法与返回状态码
    • Cookie、Session 的原理
  • MySQL
    • MySQL表存储引擎
  • 标准PHP库(SPL)
    • 数据结构
      • SplPriorityQueue - 优先队列
      • SplQueue - 队列
      • SplStack - 栈的功能
    • 接口
      • Countable - count统计接口
  • 附录:ElasticSearch
  • PHP数据结构
  • 附录:Rabbitmq
  • 附录:guzzle
  • JavaScript
    • 附录:资料
  • 疑难杂症
Powered by GitBook
On this page
  • php执行过程
  • 如何让PHP的网站运行的更快?

Was this helpful?

  1. PHP选项和运行原理

PHP的运行机制及原理

    1. 我们从未手动开启过PHP的相关进程,它是随着Apache的启动而运行的;

    1. PHP通过SAPI和Apache相连;

    1. PHP总共有三个模块:内核、Zend引擎、以及扩展层;

    1. PHP内核用来处理请求、文件流、错误处理等相关操作;

    1. Zend引擎(ZE)用以将源文件转换成机器语言,然后在虚拟机上运行它;

    1. 扩展层是一组函数、类库和流,PHP使用它们来执行一些特定的操作。比如,我们需要mysql扩展来连接MySQL数据库;

    1. 当ZE执行程序时可能会需要连接若干扩展,这时ZE将控制权交给扩展,等处理完特定任务后再返还;

    1. 最后,ZE将程序运行结果返回给PHP内核,它再将结果传送给SAPI层,最终输出到浏览器上。

php执行过程

1.扫描(scanning) ,将index.php内容变成一个个语言片段(token)

2.解析(parsing) , 将一个个语言片段变成有意义的表达式

3.编译(complication),将表达式编译成中间码(opcode)

4.执行(execution),将中间码一条一条的执行

5.输出(output buffer),将要输出的内容输出到缓冲区

学过编译原理的应该了解Lex , Lex是LEXical compiler的缩写,是个非常著名的工具,主要功能是词法分析器(scanner),描述规则采用正则表达式(regular expression)。在php源码中是 Zend/zend_language_scanner.c 去根据 Zend/zend_language_scanner.l (lex规则文件) ,来对需要执行的php文件进行词法分析 ,从而得到一个个的"词" (token),当然执行规则,也就是切分的方式还是用正则表达式做的

具体看代码 Zend/zend_language_scanner.l

$code =<<<'PHP_CODE'
<?php
//这是注释
echo "Hello, world\n";
$data = 1 + 1;
echo $data;
PHP_CODE;


print_r(token_get_all($code));

分析这个返回结果我们可以发现,源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。每一个数组的结构都是一致的,

Array(
     [0] => 316                 //tokenid,也就是"词"id 
     [1] => "Hello, world\n"        //"词"具体的内容
      [2] => 3                //所在的位置,行数
)

Token ID (在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING)。

具体的定义可以在zend_language_parser.h中找到

解析 parsing

词法分析后, 就需要根据一个个token去组成有意义的表达式

Parsing首先会丢弃Tokens Array中的多余的空格,然后将剩余的Tokens转换成一个一个的简单的表达式,例如上例中:

1.输出一个常量字符串

2.两个数字相加

3.上个表达式的结果存储在一个变量

4.输出这个变量

编译 complication

根据上面的表达式,我们要将之编译成中间码(opcode),编译成opcode后,zend引擎才会根据一条一条的opcode 去执行我们的功能!

我们怎么看到编译后的opcode代码呢? 可以用vld扩展或者parsekit相关函数可以看到编译后的opcode,上例中的opcode:

* ZEND_ECHO     'Hello World'
* ZEND_ADD       ~0 1 1  
* ZEND_ASSIGN  !0 ~0
* ZEND_ECHO     !0

注意: 1+1操作完成结果要存起来,存到临时变量 ~0 将~0赋值给$c也就是!0;

执行 execution

执行的工作具体由 Zend/zend_execute.c 来完成

如果执行是某内置函数或语句,例如array_search,会调用对应的array函数.

如果调用的是扩展,例如mysqli或pdo,则会将控制权交给这些扩展,扩展执行完后将记过返回给ZE.

全部执行完后ZE将结果返回php内核,内核再返回SAPI,最后返回到服务器,通过服务器httpresponse返回到浏览器

如何让PHP的网站运行的更快?

  • 压缩代码,去除无用的注释或空白

  • 尽量使用PHP内置函数或扩展函数

  • 用apc/xcache/opcache等缓存PHP的opcode

  • 使用多线程、多进程优化程序逻辑

  • 缓存复杂和耗时运算的结果

  • 能异步处理的任务不要马上处理,如发邮件

  • 依据资源情况对FastCGI配置合适的参数

PreviousApache 与 NginxNextPHP垃圾回收机制

Last updated 5 years ago

Was this helpful?

扫描 scanning