操作系统信号 (signal) 是 IPC (InterProcess Communication 进程间通信) 中唯一一种异步的通信方法,它的本质是用软件来模拟硬件的中断机制。用来通知某个进程有某个事件发生了。
在 linux 中我们可以用kill
命令来查看当前系统所支持的信号,如下图:
可以看到,linux支持的信号有62种 (注意,没有编号32和33的信号)。其中编号从 1 到 31 的信号属于标准信号 (也称不靠谱信号),而编号从 34 到 64 的信号属于实时信号 (也称靠谱信号)。对于同一进程来说,每种标准信号只会被记录并处理一次。并且如果发送给某个进程的标准信号的种类有多个,那么它们的处理顺序也是完全不确定的。而实时信号解决了标准信号的两个问题,即多个同种类的实时信号都可以记录在案,并且他们可以按照信号的发送顺序被处理。虽然实时信号在功能上更为强大,但是已成为事实标准信号也无法被替换掉。因此,这两大类信号一直共存着。
而 Go 中信号要从 os.Signal
讲起,该类型的声明如下:
type Signal interface {
String() string
Signal() // to distinguish from other Stringers
}
从 so.Signal 接口的声明可知,其中 Signal 方法的声明并没有实际意义。它只是作为 os.Signal
接口类型的一个标识。因此,在 Go 标准库中,所有实现它的类型的 Signal 方法都是空方法。所以实现此接口类型的值都可以表示一个操作系统信号。
在 Go 标准库中,已经包含了与不同操作系统的信号相对应的程序实体。具体来说,标准库代码包 syscall
中有与不同操作系统所支持的每一个标准信号对应的同名常量 (简称信号常量
)。这些信号常量的类型都是 syscall.Signal
。syscall.Signal
是 os.Signal
接口的一个实现类型,同时也是一个 int
类型的别名类型。
另外,如果查看 syscall.Signal
类型的 String 方法的源码,还会发现一个包级私有的、名为 signals 的变量: