2010-07-26 120 views
5

我有一個獨立的PHP腳本,我會處理從Windows操作系統發送的信號,以便在發出「kill signal」時正常關機。Windows上的信號處理

我該如何在Windows上做到這一點?

回答

3

雖然這裏唯一的其他答案是簡潔而準確的,但它缺少關於爲什麼Windows上沒有信號支持的細節。

首先,信號是一種相當有限且過時的與進程通信的方式。有更多更豐富的方式來告訴流程,它需要放棄它正在做的事情並做其他事情。即使在POSIX平臺上,信號處理程序也非常輕便 - 信號處理程序中的代碼必須準備好/能夠處理同時到達的多個信號。

PHP允許通過pcntl_signal()的信號處理程序有大量的注意事項。在它們可以被使用之前,代碼必須調整在PHP將傳遞到達處理程序的信號之前經過的「滴答」的數量。 Tick是在檢查信號處理程序狀態並運行必要的回調之前Zend(PHP的核心)將執行的指令的數量。它基本上是主執行循環內的一個繁忙循環。因此,如果遵循1的每次訂單推薦建議,那麼調整訂單將顯着減慢過程。對功能的評論表明,在大多數系統上,刻度值爲100就足夠了。理解處理程序如何工作的最簡單方法是收集信號信息後面有一個實際的信號處理程序,PHP偶爾會查詢處理程序是否被調用,發送了哪個信號等等。如果是這樣,那麼信息傳遞給用戶空間中的回調(即你的代碼)。這不是真正的信號處理,從來不會由於實際信號處理帶來的危險和困難。

第二個問題是,即使使用pcntl_signal()提供的僞信號處理程序支持,PHP也會丟失有關發生的信號的信息。如果發生多個信號情況,腳本將不會被通知多次發生某些信號。 tick值越大,發生這種情況的可能性就越大,特別是在繁忙的系統中。

Windows在很大程度上並不真正使用信號。存在用於捕獲Ctrl + C和Ctrl + Break的SetConsoleCtrlHandler()函數,其大致等同於SIGINT。缺點是必須有一個連接到進程的控制檯才能工作,並且不能由其他進程發送。 TerminateProcess()函數等同於SIGKILL,它不能在其他操作系統下被阻止/處理,並且SIGKILL信號實際上不會到達目標進程。除了這兩個功能/信號之外,它們的共同點很少。最終,Windows是一個非常不同的野獸。

查看信號的唯一原因是某種長期運行的PHP過程 - 每個人似乎都認爲語言不適合(我完全不同意,但這是一個不同的討論)。當我瞭解到即使在POSIX操作系統下PHP的信號支持的侷限性時,我也認爲它們並不是我的情況的真正答案。正確的解決方案是完全忽略信號。對於SIGINT,應編寫命令行腳本來處理提前終止的情況 - 也就是說,它們應該是冪等的。在PHP世界中,信號在很大程度上是不相關的,因爲還有其他更靈活和更豐富的解決方案,包括命名互斥/事件,套接字,文件,命名管道,共享內存等。

4

PHP不支持Windows上的信號處理。抱歉。

+1

特別是唯一的方法PHP可以處理的信號是與[pcntl_signal](http://php.net/manual/en/function.pcntl-signal.php)函數一起使用的,[pcntl擴展名](http://www.php.net) /manual/en/intro.pcntl。PHP),它不能在Windows上運行。 – Charles 2010-07-26 08:34:50