ソース配置

注意: この章の残りの部分に進む前に、お好みの Web サーバの (変更されていない) ソースを取得しておきましょう。ここでは、Apache (http://www.apache.org/ で取得できます) を使用します。また、もちろん PHP のソース (http://www.php.net/ にあります - 言うまでもないですよね?) も必要です。

PHP の動作環境を自分でコンパイルして作成できるようにしておいて ください! この方法についてはここでは触れませんが、この章の内容を 学習しようとするのなら、最低限知っておくべき基本的な内容です。

コードの内容について説明する前に、PHP のファイルを探索する助けになるよう ソースツリーの内容に慣れておくべきです。これは、拡張モジュールを 開発したりデバッグしたりする際の必須技能です。

以下の表では、主なディレクトリの内容について説明しています。

ディレクトリ内容
php-src PHP 本体のソースファイルおよびヘッダファイル。 PHP の API 定義やマクロなどはここにあります (重要)。 それ以外のものは、このディレクトリの下位階層にあります。
php-src/ext 動的モジュール、組み込みモジュールのソース置き場。 デフォルトでは、PHP 本体のソースツリーに統合された「公式」 モジュールが配置されています。PHP 4.0 以降、これらの標準 拡張モジュールを (そのモジュールがサポートしていれば) 動的モジュールとしてコンパイルすることが可能となりました。
php-src/main このディレクトリには PHP 本体のマクロや定義があります (重要)。
php-src/pear PHP Extension and Application Repository (PEAR) のディレクトリです。 ここには PEAR のコアファイルが含まれます。
php-src/sapi さまざまなサーバ用の抽象化レイヤのコードを含みます。
TSRM Zend および PHP の "Thread Safe Resource Manager" (TSRM) の場所です。
ZendEngine2 Zend エンジンのファイルがあります。この中で、Zend の API 定義やマクロなどのすべてが見つけられるでしょう (重要)。

PHP パッケージに含まれるすべてのファイルについて取り上げることは この章の範囲を超えています。しかし、以下のファイルについては 詳しく見ておくべきでしょう。

これらのファイルからインクルードされているいくつかのファイルについても 見ておきましょう。例えば、Zend エンジンの実行や PHP の初期化ファイルの サポートに関連するファイルが含まれます。これらのファイルを読んだ後で、 パッケージ全体を見回し、ファイルやモジュールの相互依存性 - 各ファイル・モジュールがお互いにどのようにかかわりあっているのか、 どのようにお互いを使用しているのか - を調べましょう。これにより、 PHP のコーディングスタイルにも慣れることができます。PHP を 拡張しようと思うなら、早いうちにこのスタイルに適応すべきです。

拡張規約

Zend は、ある規約に基づいて構築されています。 この標準規約を破ることを避けるため、 以下の節で説明する規則を守らなければなりません。

マクロ

重要なタスクのほぼ全てについて、Zend では便利なマクロを定義しています。 以下の表および図で、基本的な関数・構造体およびマクロについて 説明しています。マクロ定義のほとんどは zend.h あるいは zend_API.h にあります。この章を勉強したあとで、 これらのファイルをじっくり読んでみることをお勧めします (もちろん今この場で読んでもよいのですが、 まだこの段階ではすべてを理解することはできないでしょう)。

メモリ管理

特にサーバソフトウェアにとって、リソース管理は重大な問題です。 メモリは最も貴重なリソースのひとつなので、 メモリ管理には最大限の注意を払わねばなりません。 メモリ管理の一部は Zend によって抽象化されており、 この抽象化を使用すべきなのは明白です。この抽象化を使用することにより、 Zend はすべてのメモリ割り当てを完全に制御できるようになります。 そのブロックが使用中なのかどうかを Zend が判断し、 未使用のブロックや参照されていないブロックを自動的に開放することで メモリリークを防ぐことができます。 このために使用する関数を、以下の表にまとめます。

関数説明
emalloc()malloc() の代わりに使用します。
efree()free() の代わりに使用します。
estrdup()strdup() の代わりに使用します。
estrndup()strndup() の代わりに使用します。 estrdup() より高速で、バイナリセーフです。 複製する文字列の長さが事前にわかっている場合には、 この関数を使用することを推奨します。
ecalloc()calloc() の代わりに使用します。
erealloc()realloc() の代わりに使用します。

emalloc() および estrdup()estrndup()ecalloc()erealloc() は、内部メモリを確保します。efree() は、これらの関数で確保したブロックを開放します。 e*() 関数が管理するメモリは、 現在のプロセス内でローカルであるものとして扱われます。 このプロセスによって実行されているスクリプトが終了すると、 すぐにメモリが破棄されます。

警告

スクリプトの終了後も残り続けるメモリを確保するために、 malloc() および free() を使用することも可能です。しかし、これらの関数を使用するのは Zend API がどうしてもそれを要求している場合に限定し、 最大限の注意を払うようにしてください。それ以外の場合に使用すると、 メモリリークが発生する恐れがあります。

Zend は、マルチスレッド Web サーバをサポートするための スレッドセーフなりソース管理機能も提供しています。 この機能を使用する場合は、複数スレッドを同時に実行できるようにするため、 すべてのグローバル変数をローカルの構造体に割り当てなければなりません。 この文書が書かれた時点では Zend のスレッドセーフモードはまだ完成していません。 そのため、この文書ではこれ以上この機能について取り上げません。

ディレクトリ関数およびファイル関数

Zend モジュール内では、以下のディレクトリ関数およびファイル関数を使用しなければなりません。 これらの関数の機能はそれぞれ対応する C 関数と同じですが、 さらにスレッドレベルでの仮想実行ディレクトリがサポートされています。

Zend 関数標準 C 関数
V_GETCWD()getcwd()
V_FOPEN()fopen()
V_OPEN()open()
V_CHDIR()chdir()
V_GETWD()getwd()
V_CHDIR_FILE() ファイルのパスを引数として受け取り、 現在の実行ディレクトリをそのファイルのディレクトリに移動します。
V_STAT()stat()
V_LSTAT()lstat()

文字列の処理

Zend エンジンでは、文字列はその他の値 (整数値、論理値など) と少し異なる方法で処理されます。 これらの値を保存するために、追加のメモリを確保する必要はありません。 関数から文字列を返したい場合は、新しい文字列変数を シンボルテーブルかそれに類似のものに登録します。 その文字列が使用するメモリは、先ほど説明した e*() 関数で事前に確保しておかなければなりません (この段階では、まだあまりピンとこないかもしれません。 とりあえずは頭の片隅に置いておいてください。あとでもう一度説明します)。

複雑な型

配列やオブジェクトのような複雑な型については、扱いかたが異なります。 Zend はこれらの型を扱うための API を提供しており、 これらの型はハッシュテーブルとして保存されます。

注意: これ以降のサンプルソースでは、 読みやすさを考慮して integer などの単純な型のみを使用します。 より高度な型を作成する方法については、この章の後半で説明します。