濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > Golang信號(hào)處理及如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出詳解

Golang信號(hào)處理及如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出詳解

熱門(mén)標(biāo)簽:浙江高頻外呼系統(tǒng)多少錢(qián)一個(gè)月 濱州自動(dòng)電銷機(jī)器人排名 鄭州亮點(diǎn)科技用的什么外呼系統(tǒng) 汕頭小型外呼系統(tǒng) 釘釘有地圖標(biāo)注功能嗎 建造者2地圖標(biāo)注 黃岡人工智能電銷機(jī)器人哪個(gè)好 阿里云ai電話機(jī)器人 惠州電銷防封電話卡

Linux系統(tǒng)中的信號(hào)類型

各操作系統(tǒng)的信號(hào)定義或許有些不同。下面列出了POSIX中定義的信號(hào)。

在linux中使用34-64信號(hào)用作實(shí)時(shí)系統(tǒng)中。

命令 man 7 signal 提供了官方的信號(hào)介紹。也可以是用kill -l來(lái)快速查看

列表中,編號(hào)為1 ~ 31的信號(hào)為傳統(tǒng)UNIX支持的信號(hào),是不可靠信號(hào)(非實(shí)時(shí)的),編號(hào)為32 ~ 63的信號(hào)是后來(lái)擴(kuò)充的,稱做可靠信號(hào)(實(shí)時(shí)信號(hào))。不可靠信號(hào)和可靠信號(hào)的區(qū)別在于前者不支持排隊(duì),可能會(huì)造成信號(hào)丟失,而后者不會(huì)。

Linux支持的標(biāo)準(zhǔn)信號(hào)有以下一些,一個(gè)信號(hào)有多個(gè)值的是因?yàn)椴煌軜?gòu)使用的值不一樣,比如x86, ia64,ppc, s390, 有3個(gè)值的,第一個(gè)值是slpha和sparc,中間的值是 ix86,ia64, ppc, s390, arm和sh, 最后一個(gè)值是對(duì)mips的,連字符-表示這個(gè)架構(gòu)是缺這個(gè)信號(hào)支持的,

第1列為信號(hào)名;

第2列為對(duì)應(yīng)的信號(hào)值,需要注意的是,有些信號(hào)名對(duì)應(yīng)著3個(gè)信號(hào)值,這是因?yàn)檫@些信號(hào)值與平臺(tái)相關(guān),將man手冊(cè)中對(duì)3個(gè)信號(hào)值的說(shuō)明摘出如下,the first one is usually valid for alpha and sparc, the middle one for i386, ppc and sh, and the last one for mips.

第3列為操作系統(tǒng)收到信號(hào)后的動(dòng)作,Term表明默認(rèn)動(dòng)作為終止進(jìn)程,Ign表明默認(rèn)動(dòng)作為忽略該信號(hào),Core表明默認(rèn)動(dòng)作為終止進(jìn)程同時(shí)輸出core dump,Stop表明默認(rèn)動(dòng)作為停止進(jìn)程。

第4列為對(duì)信號(hào)作用的注釋性說(shuō)明。

標(biāo)準(zhǔn)信號(hào)-POSIX.1-1990定義

 Signal Value Action Comment
 ----------------------------------------------------------------------
 SIGHUP 1 Term Hangup detected on controlling terminal
     or death of controlling process
 SIGINT 2 Term Interrupt from keyboard
 SIGQUIT 3 Core Quit from keyboard
 SIGILL 4 Core Illegal Instruction
 SIGABRT 6 Core Abort signal from abort(3)
 SIGFPE 8 Core Floating point exception
 SIGKILL 9 Term Kill signal
 SIGSEGV 11 Core Invalid memory reference
 SIGPIPE 13 Term Broken pipe: write to pipe with no
     readers
 SIGALRM 14 Term Timer signal from alarm(2)
 SIGTERM 15 Term Termination signal
 SIGUSR1 30,10,16 Term User-defined signal 1
 SIGUSR2 31,12,17 Term User-defined signal 2
 SIGCHLD 20,17,18 Ign Child stopped or terminated
 SIGCONT 19,18,25 Cont Continue if stopped
 SIGSTOP 17,19,23 Stop Stop process
 SIGTSTP 18,20,24 Stop Stop typed at tty
 SIGTTIN 21,21,26 Stop tty input for background process
 SIGTTOU 22,22,27 Stop tty output for background process

SIGKILL和SIGSTOP信號(hào)是不能被捕獲,阻塞和忽略的。

標(biāo)準(zhǔn)信號(hào)-SUSv2 and POSIX.1-2001定義

 Signal Value Action Comment
 --------------------------------------------------------------------
 SIGBUS 10,7,10 Core Bus error (bad memory access)
 SIGPOLL   Term Pollable event (Sys V).
     Synonym for SIGIO
 SIGPROF 27,27,29 Term Profiling timer expired
 SIGSYS 12,-,12 Core Bad argument to routine (SVr4)
 SIGTRAP 5 Core Trace/breakpoint trap
 SIGURG 16,23,21 Ign Urgent condition on socket (4.2BSD)
 SIGVTALRM 26,26,28 Term Virtual alarm clock (4.2BSD)
 SIGXCPU 24,24,30 Core CPU time limit exceeded (4.2BSD)
 SIGXFSZ 25,25,31 Core File size limit exceeded (4.2BSD)

早在Linux 2.2SIGSYS, SIGXCPU, SIGXFSZ和SIGBUS(非sparc和mips架構(gòu))的默認(rèn)操作就是終止進(jìn)程(但是不產(chǎn)生coredump)

在一些unix系統(tǒng)中SIGXCPU和SIGXFSZ信號(hào)是用來(lái)終止進(jìn)程的,也是不產(chǎn)生coredunp,從Linux 2.4開(kāi)始這些信號(hào)會(huì)產(chǎn)生coredump了。

標(biāo)準(zhǔn)信號(hào)-其它信號(hào)

  Signal  Value  Action Comment
  --------------------------------------------------------------------
  SIGIOT   6  Core IOT trap. A synonym for SIGABRT
  SIGEMT  7,-,7  Term
  SIGSTKFLT -,16,-  Term Stack fault on coprocessor (unused)
  SIGIO  23,29,22 Term I/O now possible (4.2BSD)
  SIGCLD  -,-,18  Ign  A synonym for SIGCHLD
  SIGPWR  29,30,19 Term Power failure (System V)
  SIGINFO  29,-,-    A synonym for SIGPWR
  SIGLOST  -,-,-  Term File lock lost
  SIGWINCH 28,28,20 Ign  Window resize signal (4.3BSD, Sun)
  SIGUNUSED -,31,-  Term Unused signal (will be SIGSYS)

信號(hào)29是在alpha中是 SIGINFO或SIGPWR,但是在sparc中是SIGLOST。

SIGEMT沒(méi)有在POSIX.1-2001中定義, 但是在大多數(shù)Unix戲中是沒(méi)有的,他的默認(rèn)處理方式是coredump并且終止進(jìn)程。
SIGPWR(沒(méi)有在POSIX.1-2001中定義)他的默認(rèn)處理方式是忽略。

SIGIO(沒(méi)有在POSIX.1-2001中定義)在一些Unix系統(tǒng)中的處理方式也是忽略。

kill pid的作用是向進(jìn)程號(hào)為pid的進(jìn)程發(fā)送SIGTERM(這是kill默認(rèn)發(fā)送的信號(hào)),該信號(hào)是一個(gè)結(jié)束進(jìn)程的信號(hào)且可以被應(yīng)用程序捕獲。若應(yīng)用程序沒(méi)有捕獲并響應(yīng)該信號(hào)的邏輯代碼,則該信號(hào)的默認(rèn)動(dòng)作是kill掉進(jìn)程。這是終止指定進(jìn)程的推薦做法。

kill -9 pid則是向進(jìn)程號(hào)為pid的進(jìn)程發(fā)送SIGKILL(該信號(hào)的編號(hào)為9),從本文上面的說(shuō)明可知,SIGKILL既不能被應(yīng)用程序捕獲,也不能被阻塞或忽略,其動(dòng)作是立即結(jié)束指定進(jìn)程。通俗地說(shuō),應(yīng)用程序根本無(wú)法“感知”SIGKILL信號(hào),它在完全無(wú)準(zhǔn)備的情況下,就被收到SIGKILL信號(hào)的操作系統(tǒng)給干掉了,顯然,在這種“暴力”情況下,應(yīng)用程序完全沒(méi)有釋放當(dāng)前占用資源的機(jī)會(huì)。事實(shí)上,SIGKILL信號(hào)是直接發(fā)給init進(jìn)程的,它收到該信號(hào)后,負(fù)責(zé)終止pid指定的進(jìn)程。在某些情況下(如進(jìn)程已經(jīng)hang死,無(wú)法響應(yīng)正常信號(hào)),就可以使用kill -9來(lái)結(jié)束進(jìn)程。

若通過(guò)kill結(jié)束的進(jìn)程是一個(gè)創(chuàng)建過(guò)子進(jìn)程的父進(jìn)程,則其子進(jìn)程就會(huì)成為孤兒進(jìn)程(Orphan Process),這種情況下,子進(jìn)程的退出狀態(tài)就不能再被應(yīng)用進(jìn)程捕獲(因?yàn)樽鳛楦高M(jìn)程的應(yīng)用程序已經(jīng)不存在了),不過(guò)應(yīng)該不會(huì)對(duì)整個(gè)linux系統(tǒng)產(chǎn)生什么不利影響。

Go中的信號(hào)發(fā)送和處理

有時(shí)候我們想在Go程序中處理Signal信號(hào),比如收到 SIGTERM 信號(hào)后優(yōu)雅的關(guān)閉程序(參看下一節(jié)的應(yīng)用)。Go信號(hào)通知機(jī)制可以通過(guò)往一個(gè)channel中發(fā)送 os.Signal 實(shí)現(xiàn)。首先我們創(chuàng)建一個(gè)os.Signal channel,然后使用 signal.Notify 注冊(cè)要接收的信號(hào)。

package main
import (
 "fmt"
 "os"
 "os/signal"
 "syscall"
)
func main() {
 sigs := make(chan os.Signal, 1)
 done := make(chan bool, 1)
 // signal.Notify(c)
 signal.Notify(sigs, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM)
 go func() {
 sig := -sigs
 fmt.Println(sig)
 done - true
 }()

 fmt.Println("wait for signal")
 - done
 fmt.Println("got signal and exit")
 fmt.Println("run done")
}

如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出

首先什么是優(yōu)雅退出呢?所謂的優(yōu)雅退出,其實(shí)就是避免暴力殺死進(jìn)程,讓進(jìn)程在接收到信號(hào)之后,自動(dòng)的做一些善后處理,再自己自愿的退出。

Linux Server端的應(yīng)用程序經(jīng)常會(huì)長(zhǎng)時(shí)間運(yùn)行,在運(yùn)行過(guò)程中,可能申請(qǐng)了很多系統(tǒng)資源,也可能保存了很多狀態(tài),在這些場(chǎng)景下,我們希望進(jìn)程在退出前,可以釋放資源或?qū)?dāng)前狀態(tài)dump到磁盤(pán)上或打印一些重要的日志,也就是希望進(jìn)程優(yōu)雅退出(exit gracefully)。

從上面的介紹不難看出,優(yōu)雅退出可以通過(guò)捕獲SIGTERM來(lái)實(shí)現(xiàn)。具體來(lái)講,通常只需要兩步動(dòng)作:

1)注冊(cè)SIGTERM信號(hào)的處理函數(shù)并在處理函數(shù)中做一些進(jìn)程退出的準(zhǔn)備。信號(hào)處理函數(shù)的注冊(cè)可以通過(guò)signal()sigaction()來(lái)實(shí)現(xiàn),其中,推薦使用后者來(lái)實(shí)現(xiàn)信號(hào)響應(yīng)函數(shù)的設(shè)置。信號(hào)處理函數(shù)的邏輯越簡(jiǎn)單越好,通常的做法是在該函數(shù)中設(shè)置一個(gè)bool型的flag變量以表明進(jìn)程收到了SIGTERM信號(hào),準(zhǔn)備退出。

2)在主進(jìn)程的main()中,通過(guò)類似于while(!bQuit)的邏輯來(lái)檢測(cè)那個(gè)flag變量,一旦bQuit在signal handler function中被置為true,則主進(jìn)程退出while()循環(huán),接下來(lái)就是一些釋放資源或dump進(jìn)程當(dāng)前狀態(tài)或記錄日志的動(dòng)作,完成這些后,主進(jìn)程退出。

這個(gè)在我前面的一篇文章中也介紹過(guò)【=[golang的httpserver優(yōu)雅重啟][1]】https://www.jb51.net/article/137069.htm,里面介紹了一般我們使用的httpserver如何做到優(yōu)雅重啟,這里面也介紹了一些信號(hào)的使用,和優(yōu)雅重啟的思路。今天這里我們介紹的是如何優(yōu)雅退出,其實(shí)是優(yōu)雅重啟的一個(gè)簡(jiǎn)化版。

package main
import (
 "fmt"
 "os"
 "os/signal"
 "syscall"
 "time"
)
 
func main() {
 sigs := make(chan os.Signal, 1)
 // done := make(chan bool, 1) 
 // signal.Notify(sigs)
 // signal.Notify(sigs, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM)
 signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT) 
 // go func() {
 // sig := -sigs
 // fmt.Println(sig)
 // done - true
 // }()
 go func() {
 for s := range sigs {
 switch s {
 case syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT:
 fmt.Println("got signal and try to exit: ", s)
 do_exit()
 case syscall.SIGUSR1:
 fmt.Println("usr1: ", s)
 case syscall.SIGUSR2:
 fmt.Println("usr2: ", s)
 default:
 fmt.Println("other: ", s)
 }
 }
 }()
 
 
 fmt.Println("wait for signal")
 i := 0
 for {
 i++
 fmt.Println("times: ", i)
 time.Sleep(1 * time.Second)
 }
 // - done
 fmt.Println("got signal and exit")
 fmt.Println("run done")
}
 
func do_exit() {
 fmt.Println("try do some clear jobs")
 fmt.Println("run done")
 os.Exit(0)
}
kill -USR1 pid 
usr1 user defined signal 1
 
kill -USR2 pid 
usr2 user defined signal 2
 
kill -QUIT pid 
got signal and try to exit: quit
try do some clear jobs
run done

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • golang監(jiān)聽(tīng)文件變化的實(shí)例
  • golang使用信號(hào)量熱更新的實(shí)現(xiàn)示例
  • golang模擬實(shí)現(xiàn)帶超時(shí)的信號(hào)量示例代碼
  • golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解

標(biāo)簽:滄州 泰安 阿壩 駐馬店 瀘州 昭通 東營(yíng) 晉中

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Golang信號(hào)處理及如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出詳解》,本文關(guān)鍵詞  Golang,信號(hào)處理,及,如何,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Golang信號(hào)處理及如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出詳解》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于Golang信號(hào)處理及如何實(shí)現(xiàn)進(jìn)程的優(yōu)雅退出詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    临安市| 尉犁县| 永修县| 铅山县| 和平县| 明星| 根河市| 江安县| 古田县| 白城市| 昌乐县| 昆山市| 乳源| 云安县| 桑日县| 信宜市| 潮安县| 斗六市| 株洲县| 楚雄市| 龙州县| 西林县| 莱西市| 静乐县| 郓城县| 白河县| 通许县| 大渡口区| 五常市| 抚远县| 连江县| 陈巴尔虎旗| 大悟县| 滦南县| 承德县| 闻喜县| 高尔夫| 蕲春县| 闽清县| 清徐县| 铁岭市|