首頁  >  文章  >  後端開發  >  php的set_time_out和max_execution_time設定

php的set_time_out和max_execution_time設定

不言
不言原創
2018-04-26 14:27:532979瀏覽

本片文章向大家介紹了關於php的set_time_out和max_execution_time設置,有需要的朋友可以參考。


本意


#想讓一個php腳本(fpm或cli下)透過set_time_out或max_execution_time設定只執行5秒。

我原本想是這樣的程式碼

<?phpini_set("max_execution_time",5);
set_time_limit(5);for($i=0;$i<=10;$i++)
{echo $i."\n";
sleep(1);
}

但是cli下結果是

012345678910

fpm也是一樣。

思考之路

首先看手冊函數啊,摘超如下:

set_time_limit()函數和設定指令max_execution_time只會影響腳本本身執行的時間。任何發生在諸如使用system()的系統調用,流操作,資料庫操作等的腳本執行的最大時間不包括其中,當該腳本已運行時。在測量時間是實值的Windows中,情況就不是如此了。

仍然是一臉懵逼。
另外看到另外一句:

當php運行於安全模式時,此功能不能生效。除了關閉安全模式或改變php.ini中的時間限制,沒有別的辦法

特地看了一眼,不是安全模式啊。 。

然後百思不得,得到了大官人的耐心解答。

php zend引擎實作max_execute_time是使用的settimer,參數是ITIMER_PROF(也就是說這只計算用戶態和內核態使用的真正消耗的時間)
但是sleep是掛起進程一段時間,並沒有執行操作,也不存在消耗時間,所以這個sleep既不消耗核心態時間也不消耗使用者態時間。
寫了段C程式驗證了一下,確實在sleep狀態下,根本沒有時間統計,也不會觸發signal handler..

那我追一下這個[ITIMER_PRO][3 ]F參數

Description
The system provides each process with three interval timers, each decrementing in a distinct time domain. When any timer expires, a signal is sent to the process, and the timer ( potentially) restarts.

ITIMER_REAL
decrements in real time, and delivers SIGALRM upon expiration.

ITIMER_VIRTUAL

decrements only 非expiration.

ITIMER_PROF

decrements both when the process executes and when the system is executing on behalf of the process. Coupled with ITIMER_VIRTUAL, this timer is usually used pfileby in user and kernel space. SIGPROF is delivered upon expiration.

#看ITIMER_PROF選項中process executes 不就是php進程執行嗎?是進程執行沒問題,但是sleep函數會將進程掛起,所以sleep內的不算了。所以,在使用者態執行的時間,是除開你sleep後的所有時間

果真有具體差別,那麼源碼中具體怎樣體現的?再追一下

main.c下追到以下

/* {{{ proto bool set_time_limit(int seconds)
   Sets the maximum time a script can run */PHP_FUNCTION(set_time_limit)
{
    zend_long new_timeout;
    char *new_timeout_str;
    int new_timeout_strlen;
    zend_string *key;    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {        return;
    }    new_timeout_strlen = (int)zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);

    key = zend_string_init("max_execution_time", sizeof("max_execution_time")-1, 0);    if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
        RETVAL_TRUE;
    } else {
        RETVAL_FALSE;
    }
    zend_string_release(key);
    efree(new_timeout_str);
}

我們看key那一行的sizeof("max_execution_time")
然後追一下max_execution_time
還是再main.c下,有

        }        if (PG(max_input_time) != -1) {#ifdef PHP_WIN32
            zend_unset_timeout();#endif
            zend_set_timeout(INI_INT("max_execution_time"), 0);
        }

然後再zend目錄下搜尋zend_set_timeout,然後再zend_execute_api.c找到ITIMER_PROF



####################################### ############就是他了! ############

以上是php的set_time_out和max_execution_time設定的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn