摘要:如果是一個,該值會作為退出狀態碼,并且不會被打印輸出。退出狀態碼應該在范圍至,不應使用被保留的退出狀態碼。狀態碼用于成功中止程序。所以如果是一個整數,會被當成狀態碼輸出,而不是打印,所以如果想返回給前端是不可能的。
今天有小伙伴說 exit 和 die 有一點差別。我說 die 不就是 exit 的別名嗎?為了證明我的觀點,翻了翻 PHP 的源碼,在 zend_language_scanner.l 中,很容易就能發現這關鍵字是同一個 token:
"exit" { return T_EXIT; } "die" { return T_EXIT; }
所以最終也是同一個 Opcode:ZEND_EXIT。所以這兩個關鍵字沒有任何差別,這其實也沒什么好說的。
我順便提醒了小伙伴們一句:不要用 exit 輸出整數。原因也很簡單,在 PHP 官網的文檔里就能看到:
void?exit?([?string?$status?] )
void?exit?(?int?$status?)
如果?status?是一個字符串,在退出之前該函數會打印?status?。
如果?status?是一個?integer,該值會作為退出狀態碼,并且不會被打印輸出。 退出狀態碼應該在范圍0至254,不應使用被PHP保留的退出狀態碼255。 狀態碼0用于成功中止程序。
所以如果 status 是一個整數,會被當成狀態碼輸出,而不是打印,所以如果想返回給前端是不可能的。
那么這個狀態碼有什么用呢?
大家都知道 shell 腳本執行可以返回一個狀態碼,PHP 的腳本的執行返回的狀態碼是一樣的,可以在環境變量中被捕捉到:
Scholer: ~ $ php -r "exit(254);" Scholer: ~ $ echo $? 254
我的好奇心又被勾起來了:如果給的是不在 0 ~ 255 之間的狀態碼會怎么樣呢?經過測試,發現如果是大于 255 的狀態碼,會返回 status 對 256 求余之后的結果。如果是小于 0 的,在 -1 ~ - 255 之間時返回的是 status 256 求和的結果,小于 -256 的則是絕對值和 256 求余。總之都在 0 ~ 255 之間。
接著探究下去。
exit 的實現在 zend_vm_def.h 中:
ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY) { #if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED) USE_OPLINE SAVE_OPLINE(); if (OP1_TYPE != IS_UNUSED) { zend_free_op free_op1; zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); } else { zend_print_variable(ptr); } FREE_OP1(); } #endif
從代碼中我們可以很明顯的看出來通過 Z_TYPE_P 來檢測狀態碼的類型,如果是 long 的話就賦值給全局變量 exit_status(EG 這個宏就是用來便捷的訪問全局變量的),如果不是,就調用 zend_print_variable 打印出來。
Z_LVAL_P 的聲明在 zend_operators.h 中:
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) ... #define Z_LVAL(zval) (zval).value.lval
再進一步就是大家都知道的 PHP 解釋器中的變量定義了(我這份源碼還是 PHP 5.5 的版本,不是 PHP7),在 zend.h 中:
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; };
所以這里 exit_status 的值到這里還是一個長整形。
那么問題就來了,為什么最終輸出的是 0 ~ 255 之間的狀態碼呢?老實說這個問題我吃的也不是很透,這需要對 Linux 環境編程足夠熟悉才行,這里只能簡單的說一下。
通過 strace 跟蹤一下執行:
$ strace php -r "exit(258);" >& strace.log
在結果的最后兩行可以很清楚的看到:
... exit_group(258) = ? +++ exited with 2 +++
exit_group 中還是原始值,但最終會變成 2 。PHP 本身并沒有對這個值做特殊處理,但是 exit 或者 main 函數中的 return,只能使用 0 ~ 255 之間的值,其他值都會被處理。可以寫一個簡單的程序測試:
int main(int argc, char const *argv[]) { return 258; }
結果:
Scholer: ~ $ ./test Scholer: ~ $ echo $? 2
詳情參見:http://www.laruence.com/2012/02/01/2503.html
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21132.html
摘要:本節主要講解常用函數和進程池的概念,也會涉及到守護進程的知識。所以任何時候,建議預先創建好進程,也就是使用進程池的方式實現。 本節主要講解Posix常用函數和進程池的概念,也會涉及到守護進程的知識。本節難度較低。 Posix常用函數 posix_kill 向指定pid進程發送信號。成功時返回 TRUE , 或者在失敗時返回 FALSE 。 bool posix_kill ( int $...
摘要:多進程消費模型父進程等待并控制子進程的退出思路整理父進程開啟后,直接獲取到子進程的,然后存入數組,子進程出來后直接開啟業務消費代碼,然后退出,然后父進程等待子進程退出,全部退出后父進程結束代碼請在模式下運行子進程的數量如果是資源類型的變量, 多進程消費模型 父進程等待并控制子進程的退出 思路整理 父進程開啟后,直接獲取到子進程的pid,然后存入child數組,子進程fork出來后直接開...
摘要:什么是守護進程守護進程是一種特殊的進程,它的生命周期很長,它在后臺運行并且沒有控制終端這樣可以保證守護進程不會接收到各種來自終端的信號。比如等,都會使用守護進程的形式運行,確保可以一直正常的提供服務。 什么是守護進程 守護進程(daemon)是一種特殊的進程,它的生命周期很長,它在后臺運行并且沒有控制終端(這樣可以保證守護進程不會接收到各種來自終端的信號)。比如:crontab、ssh...
摘要:調用此函數,就可使當前進程脫離終端變成一個守護進程,具體內容參見。命令行程序實現守護進程化有種方法一使用這里就實現了守護進程化。單獨執行,當按下時就會中斷程序執行,會當前進程以及子進程。 一般Server程序都是運行在系統后臺,這與普通的交互式命令行程序有很大的區別。glibc里有一個函數daemon。調用此函數,就可使當前進程脫離終端變成一個守護進程,具體內容參見man daemon...
摘要:本教學使用環境介紹伺服器端資料庫語言版本本機端可以透過來產生檔案,并丟到指定的伺服器需有存取權本端上傳到遠端基本連線設定路徑設定本端的路徑遠端的路徑開始上傳關閉連線遠端下載到本端這塊跟上面的做法一樣開始下載注意跟擺放的位置跟上面完全相反關閉 本教學使用環境介紹伺服器端:Ubuntu 16.04資料庫:Mariadb 10.1.34(Mysql)語言版本:php 7.0本機端:MacOS...
閱讀 2208·2021-10-18 13:28
閱讀 2520·2021-10-11 10:59
閱讀 2345·2019-08-29 15:06
閱讀 1138·2019-08-26 13:54
閱讀 814·2019-08-26 13:52
閱讀 3151·2019-08-26 12:02
閱讀 3006·2019-08-26 11:44
閱讀 2516·2019-08-26 10:56