中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux系統中的信號類型以及Go中的信號發送和處理

發布時間:2021-09-13 23:25:07 來源:億速云 閱讀:196 作者:chen 欄目:云計算

本篇內容介紹了“Linux系統中的信號類型以及Go中的信號發送和處理”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

Linux系統中的信號類型

各操作系統的信號定義或許有些不同。下面列出了POSIX中定義的信號。
在linux中使用34-64信號用作實時系統中。
命令 man 7 signal 提供了官方的信號介紹。也可以是用kill -l來快速查看
列表中,編號為1 ~ 31的信號為傳統UNIX支持的信號,是不可靠信號(非實時的),編號為32 ~ 63的信號是后來擴充的,稱做可靠信號(實時信號)。不可靠信號和可靠信號的區別在于前者不支持排隊,可能會造成信號丟失,而后者不會。
Linux支持的標準信號有以下一些,一個信號有多個值的是因為不同架構使用的值不一樣,比如x86, ia64,ppc, s390, 有3個值的,第一個值是slpha和sparc,中間的值是 ix86,
ia64, ppc, s390, arm和sh, 最后一個值是對mips的,連字符-表示這個架構是缺這個信號支持的,
第1列為信號名;
第2列為對應的信號值,需要注意的是,有些信號名對應著3個信號值,這是因為這些信號值與平臺相關,將man手冊中對3個信號值的說明摘出如下,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列為操作系統收到信號后的動作,Term表明默認動作為終止進程,Ign表明默認動作為忽略該信號,Core表明默認動作為終止進程同時輸出core dump,Stop表明默認動作為停止進程。
第4列為對信號作用的注釋性說明。

標準信號-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信號是不能被捕獲,阻塞和忽略的。

標準信號-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架構)的默認操作就是終止進程(但是不產生coredump)
在一些unix系統中SIGXCPU和SIGXFSZ信號是用來終止進程的,也是不產生coredunp,從Linux 2.4開始這些信號會產生coredump了。

標準信號-其它信號

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)

信號29是在alpha中是 SIGINFO或SIGPWR,但是在sparc中是SIGLOST。
SIGEMT沒有在POSIX.1-2001中定義, 但是在大多數Unix戲中是沒有的,他的默認處理方式是coredump并且終止進程。
SIGPWR(沒有在POSIX.1-2001中定義)他的默認處理方式是忽略。
SIGIO(沒有在POSIX.1-2001中定義)在一些Unix系統中的處理方式也是忽略。

kill pid的作用是向進程號為pid的進程發送SIGTERM(這是kill默認發送的信號),該信號是一個結束進程的信號且可以被應用程序捕獲。若應用程序沒有捕獲并響應該信號的邏輯代碼,則該信號的默認動作是kill掉進程。這是終止指定進程的推薦做法。

kill -9 pid則是向進程號為pid的進程發送SIGKILL(該信號的編號為9),從本文上面的說明可知,SIGKILL既不能被應用程序捕獲,也不能被阻塞或忽略,其動作是立即結束指定進程。通俗地說,應用程序根本無法“感知”SIGKILL信號,它在完全無準備的情況下,就被收到SIGKILL信號的操作系統給干掉了,顯然,在這種“暴力”情況下,應用程序完全沒有釋放當前占用資源的機會。事實上,SIGKILL信號是直接發給init進程的,它收到該信號后,負責終止pid指定的進程。在某些情況下(如進程已經hang死,無法響應正常信號),就可以使用kill -9來結束進程。

若通過kill結束的進程是一個創建過子進程的父進程,則其子進程就會成為孤兒進程(Orphan Process),這種情況下,子進程的退出狀態就不能再被應用進程捕獲(因為作為父進程的應用程序已經不存在了),不過應該不會對整個linux系統產生什么不利影響。

Go中的信號發送和處理

有時候我們想在Go程序中處理Signal信號,比如收到 SIGTERM 信號后優雅的關閉程序(參看下一節的應用)。Go信號通知機制可以通過往一個channel中發送 os.Signal 實現。首先我們創建一個os.Signal channel,然后使用 signal.Notify 注冊要接收的信號。

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")
}

如何實現進程的優雅退出

首先什么是優雅退出呢?所謂的優雅退出,其實就是避免暴力殺死進程,讓進程在接收到信號之后,自動的做一些善后處理,再自己自愿的退出。
Linux Server端的應用程序經常會長時間運行,在運行過程中,可能申請了很多系統資源,也可能保存了很多狀態,在這些場景下,我們希望進程在退出前,可以釋放資源或將當前狀態dump到磁盤上或打印一些重要的日志,也就是希望進程優雅退出(exit gracefully)。
從上面的介紹不難看出,優雅退出可以通過捕獲SIGTERM來實現。具體來講,通常只需要兩步動作:
1)注冊SIGTERM信號的處理函數并在處理函數中做一些進程退出的準備。信號處理函數的注冊可以通過signal()或sigaction()來實現,其中,推薦使用后者來實現信號響應函數的設置。信號處理函數的邏輯越簡單越好,通常的做法是在該函數中設置一個bool型的flag變量以表明進程收到了SIGTERM信號,準備退出。
2)在主進程的main()中,通過類似于while(!bQuit)的邏輯來檢測那個flag變量,一旦bQuit在signal handler function中被置為true,則主進程退出while()循環,接下來就是一些釋放資源或dump進程當前狀態或記錄日志的動作,完成這些后,主進程退出。
這個在我前面的一篇文章中也介紹過[golang的httpserver優雅重啟](http://helight.info/2018-01-24/984/),里面介紹了一般我們使用的httpserver如何做到優雅重啟,這里面也介紹了一些信號的使用,和優雅重啟的思路。今天這里我們介紹的是如何優雅退出,其實是優雅重啟的一個簡化版。

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

“Linux系統中的信號類型以及Go中的信號發送和處理”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

正镶白旗| 建瓯市| 岳阳市| 平顶山市| 随州市| 溧水县| 大宁县| 新化县| 武汉市| 漳浦县| 宜宾县| 海伦市| 麟游县| 天长市| 洛阳市| 会理县| 门源| 阳谷县| 龙里县| 敦煌市| 娄底市| 黄石市| 沐川县| 永福县| 长沙市| 枣庄市| 漯河市| 柘荣县| 手机| 遵义市| 洞口县| 铜陵市| 新建县| 化德县| 汉中市| 会理县| 静乐县| 资源县| 额尔古纳市| 都江堰市| 建昌县|