面向云技术架构 - 痴者工良

  • 首页
  • 工良写的电子书
    • kubernetes 教程
    • 从 C# 入门 Kafka
    • 多线程和异步
    • 动态编程-反射、特性、AOP
    • 表达式树
  • 本站文章导航
  • 隐私政策
愿有人陪你颠沛流离
遇到能让你付出的事物或者人,都是一种运气。
能遇到,就该珍惜。或许你们最终没能在一起,但你会切实地感受到力量。
正因为这样,那段相遇才变得有价值,才没有辜负这世间的每一段相遇。
  1. 首页
  2. 编程语言
  3. Golang
  4. 正文

Go os.Signal、os.Interrupt、os.Kill 信号量的使用

2022年11月20日 790点热度 1人点赞 0条评论
内容纲要

使用示例:

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:

file

当然,如果是 Kill,那么进程可能会被直接杀死,而不会出现提示。

任务管理器杀死进程:

file
file

如果是 Linux 中,则还能有点效果。

file

停止监听信号量:

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")
    }
}
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: go interrupt kill os signal
最后更新:2022年11月20日

痴者工良

高级程序员劝退师

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2022 whuanle.cn. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

粤ICP备18051778号

粤公网安备 44030902003257号