默認的session handler啟動順序
<?php ini_set('session.gc_maxlifetime',10); ini_set('session.gc_probability ' ,1); ini_set('session.gc_divisor',5 ); class FileSessionHandler { private $savePath; function open($savePath, $sessionName) { $this->savePath = $savePath; if (!is_dir($this->savePath)) { mkdir($this->savePath, 0777); } echo __FUNCTION__."<BR>"; return true; } function close() { echo __FUNCTION__."<BR>"; return true; } function read($id) { echo __FUNCTION__."<BR>"; return (string)@file_get_contents("$this->savePath/sess_$id"); } function write($id, $data) { echo __FUNCTION__."<BR>"; return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; } function destroy($id) { $file = "$this->savePath/sess_$id"; if (file_exists($file)) { unlink($file); } echo __FUNCTION__."<BR>"; return true; } function gc($maxlifetime) { foreach (glob("$this->savePath/sess_*") as $file) { if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { unlink($file); } } echo __FUNCTION__."<BR>"; return true; } function end(){ echo '我是最后腳本結束register_shutdown_functiond調用'."<br>"; } } $handler = new FileSessionHandler(); session_set_save_handler( array($handler, 'open'), array($handler, 'close'), array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc') ); // 下面這行代碼可以防止使用對象作為會話保存管理器時可能引發的非預期行為 register_shutdown_function(array($handler,end)); session_start(); $_SESSION['name']='tb'; // session_commit(); // session_write_close(); // 如果開啟,那順序就是open read (gc) write close // session_destroy(); // session_regenerate_id(true);
運行后如下圖所示:
默認是session_start分別調用的回調函數。為open read ,然后等待腳本結束,收集$_SESSION
(默認在內存中),然后關閉腳本,然后執行write,寫入文件,然后close。
改變默認session回調順序
那么我們使用 session_commit();
或者 session_write_close();
函數調用的時候,session的機制就改變了,直接寫入文件,關閉文件。然后再執行腳本。如下圖所示:
那么session_dessory
調用的時候,就是在read之后,因為只要sesson_start
開啟,先執行的就是open 和read。
那么gc呢,我們都知道gc是根據 session.gc_probability
和 session.gc_divisor
參數控制。本例中我設置了他們的比例為5,但是現在的問題是我刷新5+次可能也調用不了一次gc。可能和我的win平台有關系。如果命中gc,而且沒有調用 session_commit();
或者 session_write_close();
函數,運行流程如下圖所示:
在win平台的遺留問題(已經測試解決)
ps:由於都是在win上測試,可能對gc的回收不是很准確,包括即使我設置為1:1,百分之百回收。在win上仍然存在這個sessionid
文件,可能原因是session 鎖機制,我在linux上測試了再分享給大家。
該問題已經澄清,請移步php Session gc機制下在window下與ununtu是不同的。