ホームページ > バックエンド開発 > PHPチュートリアル > PHP カーネルの探索: Zend 仮想マシン

PHP カーネルの探索: Zend 仮想マシン

WBOY
リリース: 2016-06-20 12:39:16
オリジナル
1029 人が閲覧しました

前回の検討で、サーバー側での PHP ファイルの実行処理には、大きく次の 2 つの処理があることが分かりました。

  1. に実行が必要なファイルを渡すphp プログラムと php プログラム 基本的な準備が完了したら、PHP と Zend エンジンを起動し、登録した拡張モジュールを読み込みます。
  2. 初期化が完了すると、スクリプト ファイルが読み取られ、Zend エンジンはスクリプト ファイルに対して字句解析と構文解析を実行します。次に、それをオペコードにコンパイルして実行します。 apc などのオペコード キャッシュがインストールされている場合、コンパイル プロセスがスキップされ、オペコードがキャッシュから直接読み取られて実行されることがあります。

2 番目のステップでは、字句解析、構文解析、中間コードのコンパイル、中間コードの実行などを総称して Zend 仮想マシンと呼びます。 Java や C# などのコンパイル済み言語と比較して、PHP は手動のコンパイル プロセスを必要とせず、コンパイルなしで実行できます。 Java には、複数のプラットフォームで統一された言語を実装する独自の Java 仮想マシンがあり、C# には、単一のプラットフォームで複数の言語を実装する独自の .NET 仮想マシンがあります。PHP も同様に、独自の Zend 仮想マシンを持っています。これらは本質的に同じであり、両方とも抽象コンピュータです。 これらの仮想マシンは、低レベル言語から別の言語を抽象化し、独自の命令セットと独自のメモリ管理システムを備えています。 最終的には、より高い抽象レベルの言語実装をより低い抽象レベルの言語実装に変換し、メモリ管理、ガベージ コレクション、その他のメカニズムなどの他の補助機能を実装して、特定の実装に対するプログラマの作業を軽減し、より多くの時間を費やすことができます。ビジネス ロジックに投資された労力。 抽象的なレベルで見ると、Zend 仮想マシンは Java や他の言語よりも高度です。ここでいう高度とは、簡単に言うと、Zend 仮想マシンが実際のマシンの実装から遠く離れていることを意味します。 。 近年、言語の発展は抽象的なものばかりが続き、根本的な変化はなく、常に機械から遠ざかっています。

ここでは、仮想マシンの過去と現在から始めて、構文の実装例とソース コード暗号化のプロセスの説明を交えながら、Zend 仮想マシンの実装原理と主要なデータ構造について説明します。そして復号化。

Wiki における仮想マシンの定義は次のとおりです: 仮想マシン (Virtual Machine) は、コンピュータ サイエンスのアーキテクチャにおいて、コンピュータ プラットフォームとエンド ユーザー環境の間で作成できる特別なソフトウェアを指します。エンドユーザーは、ソフトウェアによって作成された環境に基づいてソフトウェアを操作します。 コンピューター サイエンスでは、仮想マシンとは、実際のマシンのようにプログラムを実行できるコンピューターのソフトウェア実装を指します。

仮想マシンは、独自の命令セットと独自のメモリ管理システムを備えた抽象的なコンピューターです。 このような仮想マシンに実装された言語は、より低い抽象レベルの言語よりも明確で、学習が容易です。

PHP ファイルはどのように解析されますか? 生成された中間コードは実際の PHP コードとどのように対応していますか? 実行中にどのような中間データが保存されますか?仮想マシン全体を最適化できますか?最適化するにはどうすればよいですか?

Zend 仮想マシンのアーキテクチャ

Zend 仮想マシンの実装を概念層から抽象化すると、Zend 仮想マシンのアーキテクチャを解釈層、実行エンジン、中間データ層に分割できます。

Zend 仮想マシンのアーキテクチャ図

PHP コードの一部が Zend 仮想マシンに入ると、コンパイルと実行という 2 つのステップが実行されます。 これはインタープリター言語にとって創造的な動きですが、現在の実装は不完全です。 PHP コードが Zend 仮想マシンに入ると、これら 2 つのステップで実行されますが、これらの 2 つのステップは通常の実行プロセスでは連続しています。つまり、Java のようなものに変換されていないのと同じです。言語: コンパイルされた結果を保存するために中間ファイルが生成されます。 このような操作を毎回実行すると、PHP スクリプトのパフォーマンスに大きな損失が生じます。 APC、eAccelerator などに似たキャッシュ ソリューションもありますが、しかし、その本質は変わっておらず、2 つのステップを分離して別々に開発することはできません。

解釈層

解釈層は、Zend 仮想マシンがコンパイル プロセスを実行する場所です。これには、字句解析、構文解析、中間コードを生成するコンパイルの 3 つの部分が含まれます。 字句解析とは、実行したいPHPソースファイルからスペースやコメントを取り除き、トークンに分割し、プログラムの階層構造を処理することです。

文法分析は、定義された文法規則に従って、受け入れられたトークン シーケンスに基づいていくつかのアクションを実行することです。Zend 仮想マシンで現在使用されている Bison は、Backus Normal Form (BNF) を使用して文法を記述します。 中間コードのコンパイルと生成は、構文解析の結果に基づいて行われ、PHP5.3.1 では、Zend 仮想マシンは 135 の命令をサポートします (Zend/zend_vm_opcodes.h ファイルを参照)。これは単純な出力ステートメントです。プログラム内の複雑な再帰呼び出しであるかどうかに関係なく、Zend 仮想マシンは最終的に、作成したすべての PHP コードをこれらの 135 命令のシーケンスに変換し、実行エンジンで順番に実行します。

中間データ層

Zend 仮想マシンが PHP コードを実行する場合、中間コード、PHP 独自の関数リスト、ユーザー定義関数リスト、PHP 独自のクラス、ユーザー定義のクラス、定数、プログラムによって作成されたオブジェクト、関数またはメソッドに渡されるパラメーター、戻り値、ローカル変数、および一部の操作の中間結果など。 データが保存されるこれらすべての場所を中間データ層と呼びます。

PHP が MOD 拡張機能として Apache2 サーバーにアタッチされている場合、PHP に付属する関数リストなど、中間データ層の一部のデータが複数のスレッドで共有される可能性があります。 単一のプロセスのみを考慮すると、プロセスが作成されると、PHP に付属するさまざまな関数リスト、クラス リスト、定数リストなどがロードされます。 解釈層が PHP コードをコンパイルすると、さまざまなユーザー定義関数、クラス、または定数が前のリストに追加されますが、これらの関数の構造における特定のフィールドの割り当ては異なります。

実行エンジンが生成された中間コードを実行すると、新しい実行中間データ構造 (zend_execute_data) が Zend 仮想マシンのスタックに追加されます。これには、現在の実行のアクティブなシンボル リストのスナップショットが含まれますプロセス、いくつかのローカル変数など。

実行エンジン

Zend 仮想マシンの実行エンジンは、中間コード シーケンス (EX(opline)) に基づいて、対応するメソッドを段階的に呼び出すだけの非常に単純な実装です。 実行エンジンには、次の命令を格納するための PC レジスタのような変数はありません。Zend 仮想マシンが特定の命令を実行するとき、そのすべてのタスクが実行されると、この命令は単独で次の命令を呼び出します。シーケンス ポインタは 1 つ前に移動して次の命令を実行し、最後に return ステートメントを実行します。 これは本質的にはネストされた関数呼び出しです。

元の質問に戻りますが、PHP が字句解析、構文解析、中間コード生成の 3 つのステップを通過した後、PHP ファイルは PHP の中間コード オペコードに解析されます。 生成された中間コードと実際の PHP コードの間には、完全な 1 対 1 の対応関係はありません。ユーザーが指定した PHP コード、PHP の構文規則、および一部の内部規則に基づいて中間コードを生成するだけであり、これらの中間コードは、データと関連付けを転送するためにいくつかのグローバル変数にも依存する必要があります。生成された中間コードの実行処理は、中間コードの滑らかさと実行処理におけるグローバル変数に依存し、ステップバイステップで実行されます。もちろん、関数ジャンプに遭遇したときにオフセットも発生しますが、最終的にはオフセット ポイントに戻ります。

さらに読む

この記事のトピックのリストは次のとおりです:

  1. PHP コアの探索: SAPI インターフェースから開始
  2. PHP コアの探索: リクエストの開始と終了
  3. PHP コアの探索: リクエストのライフサイクル
  4. PHP カーネルの探索: シングルプロセス SAPI ライフサイクル
  5. PHP カーネルの探索: マルチプロセス/スレッド SAPI ライフサイクル
  6. PHP カーネルの探索: Zend Engine
  7. PHP カーネルの探索:再び SAPI について説明します
  8. PHP カーネルの探索: Apache モジュールの紹介
  9. PHP カーネルの探索: mod_php5 による PHP サポート
  10. PHP カーネルの探索: Apache の実行および関数のフック
  11. PHP カーネルの探索: 組み込み PHP
  12. PHP カーネルの探索: PHP 用 FastCGI
  13. PHP カーネルの探索: PHP スクリプトの実行方法
  14. PHP カーネルの探索: PHP スクリプトの実行の詳細
  15. PHP カーネルの探索: オペコード OpCode
  16. PHP カーネルの探索: PHP のオペコード
  17. PHP カーネルの探索: インタプリタ実行プロセス
  18. PHP カーネルの探索: 変数の概要
  19. PHP コアの探索: 変数ストレージと型
  20. PHP コアの探索: PHP のハッシュ テーブル
  21. PHP コアの探索: Zend のハッシュ テーブルについて
  22. PHPカーネルの探索: PHP ハッシュ アルゴリズムの設計
  23. PHP カーネルの探索: HashTables 記事の翻訳
  24. PHP カーネルの探索: ハッシュ衝突攻撃とは何ですか?
  25. PHP カーネルの探索: 定数の実装
  26. PHP カーネルの探索: 変数の保存
  27. PHP カーネルの探索: 変数の型
  28. PHP カーネルの探索: 変数値の操作
  29. PHP コアの探索: 変数の作成
  30. PHP コアの探索: 事前定義された変数
  31. PHP コアの探索: 変数の取得
  32. PHP コアの探索:変数の型変換
  33. PHP カーネルの探索: 弱く型指定された変数の実装
  34. PHP カーネルの探索: 静的変数の実装
  35. PHP カーネルの探索: 変数の型のヒント
  36. PHP コアの探索: 変数のライフサイクル
  37. PHP コアの探索: 変数の代入と破棄
  38. PHP コアの探索: 変数スコープ
  39. PHP コアの探索: 奇妙な変数名
  40. PHP カーネルの探索: 変数の値と型の保存
  41. PHP カーネルの探索: グローバル変数 Global
  42. PHP カーネルの探索: 変数の型変換
  43. PHP カーネルの探索: メモリ管理の開始
  44. PHP カーネルの探索: Zend Memory Manager
  45. PHP カーネルの探索: PHP のメモリ管理
  46. PHP カーネルの探索: メモリの適用と破壊
  47. PHP カーネルの探索: 参照カウントとコピーオンライト
  48. PHP カーネルの探索: PHP5.3 ガベージ コレクション メカニズム
  49. PHP カーネルの探索: メモリ管理内のキャッシュ
  50. PHP カーネル探索: コピーオンライト COW メカニズム
  51. PHP カーネルの探索: 配列とリンク リスト
  52. PHP カーネルの探索: ハッシュ テーブル API の使用
  53. PHP カーネルの探索: 配列操作
  54. PHP カーネルの探索: 配列ソース コード分析
  55. PHP カーネルの探索: 関数の分類
  56. PHP カーネルの探索: 関数の内部構造
  57. PHP カーネルの探索: 関数構造変換
  58. PHP カーネル探索: 関数を定義するプロセス
  59. PHP カーネル探索: 関数のパラメータ
  60. PHP カーネル探索: zend_parse_parameters 関数
  61. PHP コアの探索: 関数の戻り値
  62. PHP コアの探索: 仮パラメータの戻り値
  63. PHP コアの探索: 関数呼び出しと実行
  64. PHP コアの探索: 参照と関数実行
  65. PHP コアの探索: 匿名関数とクロージャ
  66. PHP コアの探索: オブジェクト指向の開始
  67. PHP コアの探索: クラスの構造と実装
  68. PHP コアの探索: クラスのメンバー変数
  69. PHP コアの探索: クラスのメンバー メソッド
  70. PHP コアの探索: クラスのプロトタイプ zend_class_entry
  71. PHP コアの探索: 定義クラスの
  72. PHP コアの探索: アクセス制御
  73. PHP コアの探索: 継承、ポリモーフィズム、抽象クラス
  74. PHP コアの探索: マジック関数と遅延バインディング
  75. PHP コアの探索: 予約クラスと特殊クラス
  76. PHP コアの探索: オブジェクト
  77. PHP コアの探索: オブジェクト インスタンスの作成
  78. PHP コアの探索: オブジェクト属性の読み取りと書き込み
  79. PHP コアの探索: ネームスペース
  80. PHP コアの探索: インターフェイスの定義
  81. PHP コアの探索: インターフェイスの継承と実装
  82. PHP コアの探索: リソース resource type
  83. PHP カーネルの探索: Zend 仮想マシン
  84. PHP カーネルの探索: 仮想マシンの字句解析
  85. PHP カーネルの探索: 仮想マシンの構文解析
  86. PHP カーネルの探索: 中間コード opcode の実行
  87. PHP カーネルの探索: コードの暗号化と復号化
  88. PHP カーネルの探索: zend_execute の具体的な実行プロセス
  89. PHP カーネルの探索: リファレンス変数とカウント ルールの説明
  90. PHP カーネルの探索: 新しいガベージ コレクション メカニズムの説明

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート