時光匆匆 光陰似箭,今年已經是小張做碼農的第N個年頭了,得益于世界上最好的語言(PHP),小張的頭發依舊茂密。但是項目寫了一個又一個,PHP、swoole用到飛起,這些年的成長卻大不如從前。
你是否也糾結于此,今天讓我們換個角度看PHP,打開源碼從C的角度看PHP,看一眼這個具有20年歷史的龐大C項目是如何工作的。
從這一刻開始,你將榮升為C程序員,你可以去溫習一下C的語法、結構體、指針和引用。
你也許會問,看個代碼git拉一下用sublime打開不就好了嗎,為什么要寫個KM。確實這樣可以看代碼,但那叫看代碼片段,不是看工程。PHP項目需要兼容Windows、Linux、Mac平臺還要處理線程安全,其代碼包含大量宏定義。我們需要借助IDE的自動跳轉和提示才能更好的閱讀。
我們需要一個IDE無錯誤提示的項目。(當你要看一個方法卻無法跳轉的時候,真是太難受了)


devCloud配置
devCloud是內部用于開發調試的linux虛擬機。沒有的小伙伴可以自己準備一臺可以ssh的CentOS虛擬機,本地虛擬機或云平臺都可以。(最好網絡能好一點,后面要傳不少東西)
cmake re2c
后面我們需要使用Clion作為C項目的IDE,Clion需要使用cmake作為項目自動化構建工具。所以我們首先需要安裝cmake devCloud上的yum默認的cmake版本為2.8.12.2符合要求,這里就直接用yum安裝。
yum install cmake
re2c 是語法生成器
yum install re2c
gdb
devCloud的gdb版本過低,這里需要手動安裝一個符合要求的版本,我選了7.8.2
wget http://ftp.gnu.org/gnu/gdb/gdb-7.8.2.tar.gz
tar zxvf gdb-7.8.2.tar.gz
cd gdb-7.8.2
./configure
make
make install
代碼拉取
選擇一個php版本,這里我用7.1.33版本。 有幾個理由:
1.項目中使用了這個版本。
2.php7對內核做了大量的改動,之前的php5已經不適合學習了。
3.后續會介紹的書籍也是基于php7.0的版本和php7.1比較接近。
4.php8目前還在測試,且和php7比較接近。
注意:本地遠程都拉取一份,要保持tag一致,兩邊都要執行下面的cmake改造
git clone https://github.com/php/php-src.git
cd php-src
git tag -l
git checkout php-7.1.33
Clion配置
工欲善其事必先利其器,要看代碼需要選一個好的IDE,多年使用PhpStorm的我推薦使用全家桶里面的Clion。一般我們不會直接使用Linux做桌面系統,這里使用Clion的遠程部署功能配合devCloud做環境部署。我的本地是Windows環境,構建編譯在遠端的devCloud進行。(用WSL也是一樣的,但是PHP的git倉庫太大在WSL中做git操作非常卡,應該是WSL文件系統的bug)
PHP cmake改造
這一步是阻止大部分同學使用Clion查看PHP源碼的主要原因。PHP項目由于歷史悠久一直使用autoconfig作為項目自動管理工具。然而Clion并不支持autoconfig,它需要項目使用cmake構建,因此我們需要對php的源碼做cmake構建改造。
https://wiki.php.net/internals/cmake 官網有一份cmake的改造文檔。
https://github.com/gloob/php-cmake github上也有對應的代碼。
但是這個文檔和代碼都太老了,應該是PHP5年代的代碼。我對這個項目做了一些升級,兼容了PHP7(水平有限可能存在問題,歡迎提PR)。
在本地執行如下命令,clone php-cmake項目,切換分支,拷貝php-cmake/cmake中的所有文件到php源代碼目錄。注意目錄合并。
git clone https://github.com/bobzhangyong/php-cmake
cd php-cmake
git checkcout feature/support_php_7_1
cp -r cmake/* ../php-src //這里是php源碼的路徑
Toolchains配置
這里設置遠程機器的信息,設置相關工具的路徑。一般會自己識別,如果不能識別可以手動輸入。會檢查版本,默認devCloud上的版本好像都不正確需要自己升級。


Deployment配置
這里需要設置代碼同步的目錄,設置好以后點按√好設置為默認。完成上面Toolchains設置后,這里可能默認出現一個devCloud的信息,但是Mappings 里面的Deployment path是/tmp/目錄下面,你可以刪除自己配置,也可以直接修改Deployment path到你需要的項目目錄。


注意:這里的Local path如果是windows上需要使用/分割路徑,不是windows默認的,否則在執行cmake構建的時候會提示目錄無法找到。


在Options里面可以設置 不要同步.phpt文件,這是php項目中的測試用例文件。(我們在拉代碼的時候其實已經會手動保證本地和遠程機器的文件一致,但是Clion還會自己同步一次,設置這個可以加速同步速度。)


同步代碼到devCloud。首次同步真的很慢,你需要耐心等待。


執行cmake構建,看看報錯不?


由于PHP cmake構建會在遠端生成一些文件,我們需要同步這些文件到本地,否則打開代碼會因為這部分.c .h文件不存在導致代碼沒有提示,各種報錯。


選擇比對方式 用Size adn Timestamp 會快一點,這里比較慢,耐心等待一下。


分析完成以后,就可以看到遠程比本地多的文件了,我們需要把他們同步到本地。最上面的
.clion.source.upload.marker 不需要同步,可以點擊紅框中的箭頭取消。 之后點擊同步。


打開php_cli.c看看源碼,是不是干干凈凈一個紅線都沒有。
斷點
光看肯定是不行的,最好能把代碼跑起來 打個斷點可以更深入的了解運行機制。你可以用gdb去斷點。我這里既然用了clion就直接用clion的斷點功能,用起來更直觀。
1、準備一個yong.php 寫一點代碼用來做測試文件。
2、這里配置運行配置。


3、設置 arguments 和 Working directory


4、把yong.php文件同步到遠端。執行以下看看。


5、打斷點。真的很爽~~


開始閱讀
目錄結構
PHP項目有很多目錄,大概功能如下:
├── CMake //用于cmake構建的文件,我們做cmake 改造的時候拷貝進去的。
├── TSRM //線程安全相關,你如果剛開始看就先忽略 不要看了
├── Zend //Zend內核的代碼
├── appveyor //一些腳本 忽略
├── build //autoconf 構建用腳本 忽略
├── cmake-build-debug //cmake構建后產物 忽略
├── ext //擴展目錄,這塊可以找感興趣的擴展看一下
├── main //主要的php邏輯
├── netware //用于兼容Netware操作系統的 直接忽略
├── pear //忽略
├── sapi //入口部分,fpm cgi 都在這里,我們可以先看一下cgi目錄
├── scripts //腳本忽略
├── tests //測試用例 忽略
├── travis //構建用 忽略
└── win32 //兼容windows系統 忽略
其實和源代碼相關的 只有這幾個目錄, 在Clion中標記為Source和Header目錄方便IDE構建索引。
main
extstandard
sapicli
Zend


從哪里開始
準備工作都做好了,還有借口不看代碼嗎?如果你還是不知道從哪里開始,那我推薦從main函數開始吧。 它在sapicliphp_cli.c的最后面。 附圖一張可以和源代碼結合起來看。
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。