返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

signal

发布于 2024-10-12 19:15:53 字数 2689 浏览 0 评论 0 收藏 0

信号是软中断(software interrupts),提供一种处理异步事件机制。

事件可能来自系统外部(用户中断),也可能来自程序内部或者内核。
作为进程间通信 (IPC)的基础构成,可向其它进程发送信号。

针对信号的操作包括:忽略和捕获。
如果不做处理,则执行默认操作。

  • SIGHUP : 控制终端关闭。
  • SIGINT : 用户产生中断字符( CTRL + C )。
  • SIGQUIT : 用户产生退出字符( CTRL + \ )。
  • SIGTERM : 进程终止,通常是 kill 操作。

大部分信号定义都在 syscall 包, os 仅有两个。

// os

var (
	Interrupt Signal = syscall.SIGINT
	Kill      Signal = syscall.SIGKILL
)

默认情况下:

  • SIGINTSIGTERMSIGHUP 导致进程终止。
  • SIGQUIT 终止进程前生成 core dump
  • SIGKILL (kill -9)和 SIGSTOP 不能被忽略和捕获。

改变信号默认行为方式,用 Notify 函数注册信号通道。

package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)

	go func() {
		for s := range sig {
			fmt.Println(s)
		}
	}()

	fmt.Println(os.Getpid())   // kill -9
	select {}
}

/*

598

interrupt            kill -s INT  598
quit                 kill -s QUIT 598
terminated           kill -s TERM 598
killed               kill -s KILL 598

*/
  • Ignore :忽略信号的默认行为。(不做任何应对,可被 Notify 重新设置)
  • Reset :按 Signal 恢复默认行为。(不包括被 Ignore 忽略的信号)
  • Stop :按 Notify chan 恢复默认行为。
func main() {
	signal.Ignore(syscall.SIGINT)  // CTRL + C 被忽略。
    fmt.Scanln()
}
func main() {
	sig1 := make(chan os.Signal)
	sig2 := make(chan os.Signal)
	
	signal.Notify(sig1, syscall.SIGINT)
	signal.Notify(sig2, syscall.SIGQUIT)

	for {
		select {
		case s := <- sig1: fmt.Println(s)
		case s := <- sig2: signal.Stop(sig1); fmt.Println(s)
		}
	}
}

// 按 CTRL + \ 后恢复 sig1 关联信号的默认行为。
// 如果换成 Reset,可指定具体的信号(或全部),与哪个 chan 无关。

除退出信号外,还常用 SIGUSR1SIGUSR2 实现通知事件,比如重载配置文件。

package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2)

	go func() {
		for s := range sig {
			switch s {
			case syscall.SIGINT:
				os.Exit(1)
			case syscall.SIGUSR1, syscall.SIGUSR2:
                fmt.Println(s, ": reload config.")
			}
		}
	}()

	fmt.Println(os.Getpid())
	select {}
}

/*

1285

user defined signal 1 : reload config.   kill -s USR1 1285
user defined signal 2 : reload config.   kill -s USR2 1285

*/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文