PHP源代碼分(fēn)析-echo實現(xiàn)詳解
echo,這(zhè)個(gè)是(shì)PHP運用(yòng)得(de)ε♠最多(duō)的(de)标記之一(yī),算(suàn)不(b₹'ù)上(shàng)是(shì)函數(sh♠£ ù),PHP手冊裡(lǐ)這(zhè)麽寫的(de),因為(w耧i)它沒有(yǒu)返回值。今天好(hǎo)奇就(jiù)去(qù <∞→)看(kàn)看(kàn)PHP的(de)源代碼,因為(wèi)ech✘®±o不(bù)是(shì)一(yī)般的(de)函數(shù),所以找起來(láε✘₽€i)比較費(fèi)勁,一(yī)般的(de)函數♠¶÷&(shù)隻要(yào)搜索PHP_FUNCβTION(fun_name)基本就(jiù)能(néng)找著(♦×&zhe)函數(shù)的(de)實現(xiàn)方式,但(d§₹£₽àn)是(shì)PHP是(shì)一(yī)門(mén)腳本語言,所以的(dα'e)符号都(dōu)會(huì)先經過詞法解©☆¶析和(hé)語法解析階段,這(zhè)兩個(gè)階段是($σ₽ shì)由lex&yacc實現(xiàn)的(de) ✔。對(duì)應的(de)文(wén)件(jiàn)在p"¶&hp_source/Zend/目錄下(xià±α§')面的(de)zend_language_parser.y及zend♥✔_language_scanner.l
首先看(kàn)zend_language_scanner.l文(wé₩✔≈n)件(jiàn),1077行(xíng∑®>):
<ST_IN_SCRIPTING>“echo” {
return T_ECHO;
}
ZEND引擎在讀(dú)取一(yī)個(♣≈♠gè)PHP文(wén)件(jiàn)之後&↕♣$會(huì)先進行(xíng)詞法分(fēn)析ε©δ,就(jiù)是(shì)用(yòng)lex掃描,把對(duì)應的(♠≈×de)PHP字符轉換成相(xiàng)應的$₹₹♦(de)标記(也(yě)叫token),比如(rú)你(n♥±ǐ)echo$a;在碰到(dào)這(zhè)→§↔ε句首先會(huì)匹配到(dào)echo,符合上(shànπ♦g)面的(de)規則,然後就(jiù)返回一(yī)個(gè)T_E×∑↑CHO标記,這(zhè)個(gè)在後面的(de)語法分(fē£ ¥n)析會(huì)用(yòng)上(shàng),也(yě)就(j↑♠iù)是(shì)在zend_language_parse™∞"r.y文(wén)件(jiàn)中:
unticked_statement:
。。。。中間(jiān)有(yǒu)省略
| T£λ_GLOBAL global_var_list ‘;’
|  $§≤;T_STATIC static_var_list ‘;’
| &nγ©γbsp;T_ECHO echo_expr_list ‘;↔γ’
| T♥ ™_INLINE_HTML &δ∞εnbsp; &×★Ω♠nbsp; ♥>≥ { ze↓&★>nd_do_echo(&$1 TSRMLS_CC); }
看(kàn)到(dào)了(le)T_ECHO,後面跟著(zhe♦₽)echo_expr_list,再搜這(zhè)個(gè)字符串π± ,找到(dào):
echo_expr_list:
echo_expr_list ‘,’ expr { zend_do_ec♣♠ ho(&$3 TSRMLS_CC); }   ✘; δ>♥ //第1行(xíng),
| &nbs• £p; expr  ¶÷;  φ>; ∞© § &nbs±÷↑Ωp; {±& zend_do_echo(&$1 TS↑₽δRMLS_CC); } //第2行(xíng)
對(duì)于第1行(xíng)就(jiù≈•)像 echo $var_1,$var_2,
執行(xíng)動作(zuò)就(jiù)是(shì)ze>±nd_do_echo()函數(shù),在Zend/目錄下(xià)面搜索♣¶γ↓一(yī)下(xià)這(zhè)個(gè)函數(shù),就(jiù)∑"®α能(néng)知(zhī)道(dào)這(zhè)個(gè)函γ♠γ數(shù)是(shì)在zend_compile.c文(™ ✘wén)件(jiàn)裡(lǐ)面實現(xiàn)的(de):
void zend_do_echo(znode *arg TSRMLS∏<✔σ_DC)
{
♣'zend_op *opline = get_ne∑xt_op(CG(active_op_array) TSRMφαλ¥LS_CC);
opline->€"&opcode = ZEND_ECHO;
opline->&∑;op1 = *arg;
"σ♠δ SET_UNUSED(opline->op2);
}
這(zhè)個(gè)函數(shù)沒有(yǒu)∞↔δ做(zuò)什(shén)麽真正的(de)輸出動作(zuò←),隻是(shì)把這(zhè)個(gè)zend_op∏φ操作(zuò)數(shù)的(de)類型置為(wèi)Z←∑∞δEND_ECHO,把要(yào)輸出的(de)內(nèi)容≥♣♣≈賦給opline->op1 = *arg;
真正的(de)輸出動作(zuò)是(shì)由ZEND引擎實現(xiàn)≈β✔的(de),要(yào)知(zhī)道(d♠'ào)所有(yǒu)的(de)操作(zuò)數(shù)都(dōuλ∏←)會(huì)被ZEND引擎執行(xíng)。再搜索一(yī)下(xià$σ)ZEND_ECHO,在zend_vm_def.h頭文(wén)件(jiàn)≈♣♦÷裡(lǐ)面找到(dào)它的(de)定義:
ZEND_VM_HANDLER(40, ZEND_EC<✔γ±HO, CONST|TMP|VAR|CV, ANY)
{
zend_op *opline = EX(opline);
zend_free_op free_op1;
zval z_copy;
zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R≥♣₽✘);
if (Z_TYPE_P(z) == IS_Oλ♣BJECT && Z_OBJ_☆ §&HT_P(z)->get_method != NULL★×< &&
zend_std_cast_object_tostring§"(z, &z_copy, IS_STRINGφ↑ TSRMLS_CC) == SUCCESS) {
zend_print_variable(±&z_copy);
zval_dtor(&z_copy);
} else {
zend_print_variable(z);
}
FREE_OP1();
ZEND_VM_NEXT_OPCODE();
}
看(kàn)紅(hóng)色的(de)兩個(gè)代碼段€♣≤,如(rú)果遇到(dào)的(de)變量是(shì)一(yī≤↕)個(gè)對(duì)象,就(jiù)調用(yòng)zend_s"✔td_cast_object_tostring把對(duì)象轉化(hu☆€à)為(wèi)字符串,然後再調用(yòng)§∏zend_print_variable()輸出。
剩下(xià)的(de)工(gōng)作(zuò)就(jiù)是(sh&♣δì)找出zend_print_variable的(de)實現(x<> πiàn)了(le)。不(bù)過我發現(xi♣ ♦•àn)這(zhè)個(gè)函數(shù)還(hái≤< ™)真的(de)隐藏得(de)非常深,經過了(le)∏★♥一(yī)層又(yòu)一(yī)層的(de)δβ±調用(yòng),最後給找了(le)再來(lái)。
在/Zend/zend_variables.c下(xià)面實現(₹↓&₹xiàn)了(le)zend_print÷β _variable函數(shù):
ZEND_API int zend_pri'πnt_variable(zval *var)
{
return ✘↓♦zend_print_zval(var, 0);
}
在/Zend/zend.c文(wén)件(jiàn)裡(lǐ)面實現(✔∞"σxiàn)了(le)zend_print_↔€±zval
ZEND_API int zend_print↑ ≈_zval(zval *expr, int indent)
{
★™'✘ return zend_print_zval_ex(zend_write, ♣σexpr, indent);
}
ZEND_API int zend_print_zval_ex(zen♠↓™d_write_func_t write_✘™±func, zval *expr, int inden↓Ω←↔t)
{
♠€εΩ zval expr_copy;
int use"α™α_copy;
  ; zend_make_printable_zval(expr, &e±±xpr_copy, &use_copy≈≈);
₩×if (use_copy) {
σ  ₩"; expr = &expr_copy;
♦γ }
if∑£±¶ (expr->value.str.len=₹λ'=0) { /* optimize away empt£↑y strings */
&nbαsp; &nbs♠"φ★p; if (use_copy) {
♣ ε± <↔zval_dtor(expr);
 <★>; }
&nbsα♠↕÷p; return 0;
→$}
&nb★φsp; write_func(expr->value.str.va≥♠l, expr->value.str.l ↑™en);
&nbs↕¶λ§p; if (use_copy) {
&nbs&∑p; &nbsφβp; zval_dtor(expr);
±≥ }
<∏'return expr->value.str.len;
}
注意上(shàng)面函數(shù)标紅(hóng)§€♠的(de)三個(gè)部分(fēn),
ZEND_API int zend_print_zval_ex(zendδ→_write_func_t write_func, zval*expr, Ω•intindent)第一(yī)個(gè)參數(shù)是(sh✘λ ì)一(yī)個(gè)函數(shù)指針(忘了(le)是(γ→ δshì)不(bù)是(shì)這(zhè)樣叫,不(bù)明(míng)白(bεα$ái)的(de)可(kě)以百度一(yī)下(xià)),所" ♥✘以實際上(shàng)最後調用(yòng)的(de)是(shì€φπ)zend_write(expr,indent);
zend_write也(yě)是(shì)一(yī)個 ♠(gè)函數(shù)指針,在/Zend/ ♠zend.c裡(lǐ)面:
typedef int (*zend_write_func_t)(con₩αβst char *str, uint str_leng•♥☆∏th);
ZEND_API zend_write_func_t zend_wrλ♦ite;
而zend_write的(de)初始化(huà)是(sh¶✘ì)在zend_startup()函數(shù)裡(lǐ)面,這(® zhè)是(shì)zend引擎啓動的("✔₹de)時(shí)候需要(yào)做(zuò)的(de)一¥α(yī)些(xiē)初始化(huà)工(gōnπ•g)作(zuò),有(yǒu)下(xià)面一§✔✘"(yī)句:
zend_write = (zend_write_func_§"γλt) utility_functions->write_functi☆®on;
然後是(shì)在/main/目錄下(xià)面的(de)main.δ$←÷c文(wén)件(jiàn)裡(lǐ)面的(de)php_&'module_startup函數(shù)調₹用(yòng)了(le)zend_startδσ up()函數(shù),就(jiù)是(≠∏★shì)說(shuō)PHP作(zuò)為(wèi)模塊啓動的(de)↔ ∏時(shí)候需要(yào)進行(xíng)的(de)一(yī)些(x£≈iē)初始化(huà)動作(zuò)都(dōu)在這(zhè)裡(lǐ)€"φ執行(xíng)了(le),在這(zhè)個(gè←↓≈)函數(shù)裡(lǐ)面調用(yòng)了(le)下(xià)面幾句:✔¥
zuf.write_function = php_body_₽•"write_wrapper;
zuf.fopen_function =φ php_fopen_wrapper_for_zend;
zuf.message_handler = php_message_handl → >er_for_zend; &n∑ππbsp;
zuf.block_interruptions = sapi_×ε♦↕module.block_interruptions;
zuf.unblock_interruptions = sapi_modul¶≤e.unblock_interruptionsε;
zuf.get_configuration_di €rective = php_get_configur₩<ation_directive_for_zend;
zuf.ticks_function = phpεα_run_ticks;
zuf.on_timeout = php_oβ n_timeout;
zuf.stream_open_function ∏♠= php_stream_open_for_zend;
zuf.vspprintf_function = vspprin↕×→tf;
zuf.getenv_function = sapi_geλ∏δtenv;
zend_startup(&zuf, NULL, 1)¶>;
zuf是(shì)一(yī)個(gè)zend_utility_f↕β≥÷unctions結構體(tǐ),注意上(shàng)面紅(hó€>ng)色的(de)兩句,這(zhè)樣就(≤♦÷jiù)把php_body_write_wrapp↔<β∏er函數(shù)傳給了(le)zuf.write_functioγλ♦n,後面還(hái)有(yǒu)好(hǎo)<↕幾層包裝,最後的(de)實現(xiàn)是(shì)在/mδ≥ain/output.c文(wén)件(jiàn)裡(lǐ)✔®¶面實現(xiàn)的(de),是(shì) ±下(xià)面這(zhè)個(gè)函數(shù):
PHPAPI int php_default_ouσΩtput_func(const char *str, uint$¶ str_len TSRMLS_DC){♠♠
fw±<↓rite(str, 1, str_len, stderr);α♥×β
∑Ω→• return str_len;
}
可(kě)見(jiàn),php裡(lǐ)面的(deα≥✔ )echo最後實際上(shàng)是(shì)通(tōng)過調用(yò☆±£≤ng)C裡(lǐ)面的(de)fwrite函數(shù)實♠∑現(xiàn)的(de),隻是(shì)包裝了(le)十幾層,暫時(sh₹→↕×í)想不(bù)通(tōng)為(wèi)什(sh§∑én)麽要(yào)經過這(zhè)麽多(duō)層的(de)包裝,經過&這(zhè)麽多(duō)層的(de)調用(yòng),難怪PHP→☆→®的(de)性能(néng)沒法跟C比了(le)。