理解 SIGINT 與 SIGTERM:Unix 系統中中斷與終止訊號的差異與應用
在 Unix 或類 Unix 系統(如 Linux 與 macOS)中,進程控制是一個非常核心的概念,而系統訊號(Signal)正是與進程互動的主要機制之一。其中,SIGINT 與 SIGTERM 是開發者經常會遇到的兩種終止訊號。雖然它們都能讓一個應用程式「停止」,但其來源、用途與處理方式卻有所不同。
🔹 什麼是 Signal?
Signal 是作業系統提供的一種機制,用來向進程發送非同步通知,例如要求中止、暫停、重啟等。當一個 Signal 被送出時,目標進程可以選擇:
- 接受並執行預設動作(例如終止進程);
- 忽略這個訊號;
- 安裝自訂的 signal handler 處理邏輯。
🔸 SIGINT(中斷信號)
- 信號編號:2
- 預設動作:終止進程
- 來源:通常由使用者手動發送,最常見的方式是按下 Ctrl+C。
- 用途:模擬人工中斷程式的執行,常用於測試或主動終止前台程式。
✅ 範例:
$ ./myProgram
# 用 Ctrl+C 中斷
此時系統會送出 SIGINT 到前台程序,若程式未處理這個信號,將會直接結束。
🔸 SIGTERM(終止信號)
- 信號編號:15
- 預設動作:終止進程
- 來源:可透過指令如 kill 發送,由其他程式或系統主動通知。
- 用途:優雅地請求進程結束,給予其時間做資源釋放、狀態儲存等清理動作。
✅ 範例:
$ kill <pid>
這會對指定的進程發送 SIGTERM。與 SIGKILL 不同,SIGTERM 是「可攔截」的,允許進程自訂處理行為。
⚖️ SIGINT vs SIGTERM 比較表
❌ Unsupported block ($table)🛠 開發應用範例(Swift)
以下是一段 Swift 程式碼,示範如何註冊 SIGINT 與 SIGTERM 的 handler,並進行清理操作:
import signal
import time
def handle_signal(signum, frame):
print(f"Received signal {signum}, cleaning up...")
exit(0)
signal.signal(signal.SIGINT, handle_signal)
signal.signal(signal.SIGTERM, handle_signal)
print("Running... Press Ctrl+C to stop")
while True:
time.sleep(1)
🧠 進階建議
- 使用 sigaction 替代 signal() 可提高可攜性與安全性。
- 若程式使用多執行緒或複雜資源(如 I/O、網路),建議用主線程監控退出旗標,而非在 handler 中直接清理。
🧾 結語
SIGINT 與 SIGTERM 看似簡單,實際上卻是開發可靠、可控制終止邏輯的重要基石。無論你在撰寫伺服器、CLI 工具、長時間執行的服務或背景工作者,理解這兩個訊號的差異與使用方式,都能幫助你打造更穩健的應用程式。