写点什么

Go:gsignal,信号大师

用户头像
陈思敏捷
关注
发布于: 2020 年 06 月 28 日
Go:gsignal,信号大师

ℹ️ 本文基于 Go 1.13。


signal 包提供了信息处理器并允许 Go 程序与传入的信息进行交互。让我们在深入内部前先从 listener(监听者)开始。


订阅

信号的订阅是通过通道完成的。这是一个监听任何中断信号或者调整终端大小的程序示例。



每一个os.Signal 通道监听它自己的事件集。这是上面例子里订阅工作流的图:



Go 还为通道提供了停止通知的功能Stop(os.Signal) 或者忽略信号的功能Ignore(...os.Signal) 。



该程序不能被CTRL+C 中断并且永远不会停止,因为在第二次从该通道接收之前,该通道已停止监听用于终端调整大小的信号。现在让我们看一下处理传入信号的listenerprocess是如何构建的。


gsignal

在初始阶段,signal生成一个 goroutine,该 goroutine 循环运行并充当处理信号的消费者。此循环将一直休眠直到得到通知。这是第一步:



然后当一个信号程序时候,信号处理程序将委托一个特殊的 goroutine gsignal 来处理。这个 goroutine 使用固定的且无法增长的较大栈(32k,以满足不同操作系统的需求)。每个线程 M 都有一个内部 gsignal goroutine 来处理这些信号。这是更新的图:



gsignal分析信号检查是否可处理,并唤醒睡眠的 goroutine 并将信号发送到队列:



同步信号,类似SIGBUSSIGFPE ,无法被管理,将会被转换成 panic


然后,此循环 goroutine 可以对其进行处理。它会查找首先订阅该事件的通道,然后把信号推送给它们:



循环处理信号的 goroutine 可以通过go tool trace 可视化:



gsignal锁定或者阻塞会使信号处理陷入困境。由于其固定大小也无法再分配内存。这也是为什么信号处理链中会有两个独立 goroutine 的重要性:一个负责处理到达信号的排队,另一个在同一队列中循环处理他们。


现在,我们可以使用新组件更新第一部分的说明:



编译整理自  Go: gsignal, Master of Signals

博客地址:https://www.chenjie.info/2461


本文首发于我的公众号:


发布于: 2020 年 06 月 28 日阅读数: 74
用户头像

陈思敏捷

关注

多动脑不痴呆 2017.12.21 加入

gopher

评论

发布
暂无评论
Go:gsignal,信号大师