當然,討論 PHP 包裡面全部每一個檔案無疑是超出了本章的範圍,但你還是應該仔細看一下下面的幾個檔案:
php-src/main/php.h, 位於PHP 主目錄。這個檔案包含了絕大部分 PHP 宏及 API 定義。
php-src/Zend/zend.h, 位於 Zend 主目錄。這個檔案包含了絕大部分 Zend 宏及 API 定義。
php-src/Zend/zend_API.h, 也位於 Zend 主目錄,包含了Zend API 的定義。
除此之外,你也應該注意一下這些檔案所包含的一些檔案。舉例來說,哪些檔案與 Zend 執行器有關,哪些檔案又為 PHP 初始化工作提供了支援等等。在閱讀完這些檔案之後,你還可以花點時間再圍繞PHP包來看一些檔案,瞭解一下這些檔案和模組之間的依賴性――它們之間是如何依賴於別的檔案又是如何為其他檔案提供支援的。同時這也可以協助你適應一下 PHP 創作者們代碼的風格。要想擴充 PHP,你應該儘快適應這種風格。
擴充規範
Zend 是用一些特定的規範構建的。為了避免破壞這些規範,你應該遵循以下的幾個規則:
宏
幾乎對於每一項重要的任務,Zend 都預先提供了極為方便的宏。在下面章節的圖表裡將會描述到大部分基本函數、結構和宏。這些宏定義大多可以在 Zend.h 和 Zend_API.h 中找到。我們建議您在學習完本節之後仔細看一下這些檔案。(當然你也可以現在就閱讀這些檔案,但你可能不會留下太多的印象。)
記憶體管理
資源管理仍然是一個極為關鍵的問題,尤其是對伺服器軟體而言。資源裡最具寶貴的則非記憶體莫屬了,記憶體管理也必須極端小心。記憶體管理在 Zend 中已經被部分抽象,而且你也應該堅持使用這些抽象,原因顯而易見:由於得以抽象,Zend 就可以完全控制記憶體的分配。Zend 可以確定一塊記憶體是否在使用,也可以自動釋放未使用和失去引用的記憶體塊,因此就可以避免記憶體流失。下表列出了一些常用函數:
函數 |
描述 |
emalloc() |
用於替代 malloc()。 |
efree() |
用於替代 free()。 |
estrdup() |
用於替代 strdup()。 |
estrndup() |
用於替代strndup()。速度要快於 estrdup() 而且是二進位安全的。如果你在複製之前預Crowdsourced Security Testing道這個字串的長度那就推薦你使用這個函數。 |
ecalloc() |
用於替代 calloc()。 |
erealloc() |
用於替代 realloc()。 |
emalloc(), estrdup(), estrndup(), ecalloc(), 和 erealloc() 用於申請內部的記憶體,efree() 則用來釋放這些前面這些函數申請的記憶體。e*() 函數所用到的記憶體僅對當前本地的處理請求有效,並且會在指令碼執行完畢,處理請求終止時被釋放。
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 來操作這些類型。