Go 内部如何处理 os.Signal 通道?
How an os.Signal channel is handled internally in Go?
当有代码时:
package main
import (
"os"
"os/signal"
)
func main() {
sig := make(chan os.Signal, 1)
signal.Notify(sig)
<-sig
}
运行没有问题,当然会阻塞,直到您发送中断程序的信号。
但是:
package main
func main() {
sig := make(chan int, 1)
<-sig
}
抛出此错误:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/home/user/project/src/main.go:5 +0x4d
exit status 2
虽然我理解为什么从 int
频道读取会导致死锁,但我只是怀疑
os.Signal
不会,因为它的通道可能会受到来自 "the outside" 的写入,嗯,
它处理信号,它们来自程序外部。
我的怀疑是不是有点正确?如果是这样,运行时处理此问题的方式与其他通道类型有何不同?
谢谢!
您遇到了死锁,因为尝试从通道接收消息但不存在其他非发送方的 goroutine 运行。同时调用 signal.Notify
在后台启动 watchSignalLoop()
goroutine,您可以在此处验证实现细节 https://golang.org/src/os/signal/signal.go.
频道不关心元素类型,除非你的元素类型大于 64kB(严格来说,还有其他细微差别,请检查实现)。
不要猜测运行时是如何工作的,进行研究。例如,您可以检查调用 make(chan int)
时会发生什么。您可以执行 go tool compile -S main.go | grep main.go:line of make chan
并检查从运行时包中调用了哪个函数。然后跳转到这个文件并花时间了解实现。与其他事物相比,您会发现通道的实现简单明了
希望对您有所帮助!
当有代码时:
package main
import (
"os"
"os/signal"
)
func main() {
sig := make(chan os.Signal, 1)
signal.Notify(sig)
<-sig
}
运行没有问题,当然会阻塞,直到您发送中断程序的信号。
但是:
package main
func main() {
sig := make(chan int, 1)
<-sig
}
抛出此错误:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/home/user/project/src/main.go:5 +0x4d
exit status 2
虽然我理解为什么从 int
频道读取会导致死锁,但我只是怀疑
os.Signal
不会,因为它的通道可能会受到来自 "the outside" 的写入,嗯,
它处理信号,它们来自程序外部。
我的怀疑是不是有点正确?如果是这样,运行时处理此问题的方式与其他通道类型有何不同?
谢谢!
您遇到了死锁,因为尝试从通道接收消息但不存在其他非发送方的 goroutine 运行。同时调用 signal.Notify
在后台启动 watchSignalLoop()
goroutine,您可以在此处验证实现细节 https://golang.org/src/os/signal/signal.go.
频道不关心元素类型,除非你的元素类型大于 64kB(严格来说,还有其他细微差别,请检查实现)。
不要猜测运行时是如何工作的,进行研究。例如,您可以检查调用 make(chan int)
时会发生什么。您可以执行 go tool compile -S main.go | grep main.go:line of make chan
并检查从运行时包中调用了哪个函数。然后跳转到这个文件并花时间了解实现。与其他事物相比,您会发现通道的实现简单明了
希望对您有所帮助!