内容目录
使用示例:
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
// Block until a signal is received.
s := <-c
fmt.Println("Got signal:", s)
}
Notify 的函数定义如下:
func Notify(c chan<- os.Signal, sig ...os.Signal)
os.Signal
表示信号量,信号量有多种,例如 Interrupt
、Kill
,因此需要使用通道接收,这样可以可以避免信号丢失。
c := make(chan os.Signal, 1)
然后监听种类型的信号量:
signal.Notify(c, os.Interrupt, os.Kill)
os.Interrupt
表示中断;
os.Kill
表示杀死;
正常情况下,进程被按下 Ctrl+C
,会被终止。但是如果自己订阅了信号量,那么可以一直不停止。
下面示例可以接收两个信号量,然后执行某些操作再退出进程:
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
ci := make(chan os.Signal, 1)
ck := make(chan os.Signal, 1)
sleep := make(chan bool, 1)
signal.Notify(ci, os.Interrupt)
signal.Notify(ck, os.Kill)
go interrupt(ci, sleep)
go kill(ck, sleep)
<-sleep
}
func interrupt(ci chan os.Signal, sleep chan bool) {
s := <-ci
fmt.Println("进程被中断:", s)
sleep <- true
}
func kill(ck chan os.Signal, sleep chan bool) {
s := <-ck
fmt.Println("进程被杀死", s)
sleep <- true
}
按下 Ctrl+C
:
当然,如果是 Kill,那么进程可能会被直接杀死,而不会出现提示。
任务管理器杀死进程:
如果是 Linux 中,则还能有点效果。
停止监听信号量:
signal.Stop(ci)
Go 中支持的信号量:
信号值 | 值 | 动作 | 说明 |
---|---|---|---|
SIGHUP | 1 | Term | 终端控制进程结束(终端连接断开) |
SIGINT | 2 | Term | 用户发送INTR字符(Ctrl+C)触发 |
SIGQUIT | 3 | Core | 用户发送QUIT字符(Ctrl+/)触发 |
SIGILL | 4 | Core | 非法指令(程序错误、试图执行数据段、栈溢出等) |
SIGABRT | 6 | Core | 调用abort函数触发 |
SIGFPE | 8 | Core | 算术运行错误(浮点运算错误、除数为零等) |
SIGKILL | 9 | Term | 无条件结束程序(不能被捕获、阻塞或忽略) |
SIGSEGV | 11 | Core | 无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作) |
SIGPIPE | 13 | Term | 消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作) |
SIGALRM | 14 | Term | 时钟定时信号 |
SIGTERM | 15 | Term | 结束程序(可以被捕获、阻塞或忽略) |
SIGUSR1 | 30,10,16 | Term | 用户保留 |
SIGUSR2 | 31,12,17 | Term | 用户保留 |
SIGCHLD | 20,17,18 | Ign | 子进程结束(由父进程接收) |
SIGCONT | 19,18,25 | Cont | 继续执行已经停止的进程(不能被阻塞) |
SIGSTOP | 17,19,23 | Stop | 停止进程(不能被捕获、阻塞或忽略) |
SIGTSTP | 18,20,24 | Stop | 停止进程(可以被捕获、阻塞或忽略) |
SIGTTIN | 21,21,26 | Stop | 后台程序从终端中读取数据时触发 |
SIGTTOU | 22,22,27 | Stop | 后台程序向终端中写数据时触发 |
其他示例:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
SigChan := make(chan os.Signal, 1)
signal.Notify(SigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
sig := <-SigChan
switch sig {
case syscall.SIGHUP:
fmt.Println("\nSIGHUP signal generated")
case syscall.SIGINT:
fmt.Println("\nSIGINT signal generated")
case syscall.SIGTERM:
fmt.Println("\nSIGTERM signal generated")
case syscall.SIGQUIT:
fmt.Println("\nSIGQUIT signal generated")
default:
fmt.Println("\nUNKNOWN signal generated")
}
}
文章评论