为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中捕获任意 UNIX 信号

如何在 Go 中捕获任意 UNIX 信号

Go
守候你守候我 2022-06-13 15:51:29
我可以使用信号包捕获信号,但是如何捕获从 34(SIGRTMIN)到 64(SIGRTMAX)的信号(链接)?Golang 称它们为“信号 34”、“信号 64”等,但这已经超出了重点。当我运行“pkill -34”时,我希望我的应用程序注意到它。当我捕获所有信号时,我可以捕获它们:sigChan := make(chan os.Signal, 1) signal.Notify(sigChan)但是我不想捕捉所有信号,我只想要我之前提到的那些。我也知道我可以捕获单个信号,例如:signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)但这需要信号常数,我找不到与我想要捕获的信号相对应的常数。有任何想法吗?
查看完整描述

2 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

简短的回答:


您可以将新信号声明为 type 的类型化常量syscall.Signal:


const (

    SIGRTMIN = syscall.Signal(0x22)

)

长答案(它是如何工作的):


signal.Notify函数签名是:


Notify(c chan<- os.Signal, sig ...os.Signal)

哪里os.Signal是这样定义的接口:


// A Signal represents an operating system signal.

// The usual underlying implementation is operating system-dependent:

// on Unix it is syscall.Signal.

type Signal interface {

    String() string

    Signal() // to distinguish from other Stringers

}

通常你会使用signal.Notify你的例子中的函数:


signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)

因此,如果我们检查包中这些常量的实现,syscall我们会看到:


SIGKILL   = Signal(0x9)

包中的 thisSignal是syscall定义的类型:


// A Signal is a number describing a process signal.

// It implements the os.Signal interface.

type Signal int


func (s Signal) Signal() {}


func (s Signal) String() string {

    // ... a few lines of code

}

它只是一个int带有无操作Signal()方法和 Stringer 实现的底层。


int因此,您可以通过转换任意值来为要捕获的信号以相同的方式声明自己的常量:


const (

    SIGRTMIN = syscall.Signal(0x22)

)


signal.Notify(sigChan, SIGRTMIN, /* etc. */)


查看完整回答
反对 回复 2022-06-13
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

- - - - - - - - - - - - - 回答 - - - - - - - - - - - - ---


由于 [blackgreen][3],此问题已得到解决。


我制作了一个小片段来轻松捕获所有 SIGRT 信号:


package main


import (

    "fmt"

    "syscall"

    "os/signal"

    "os"

)


func getSIGRTchannel() chan os.Signal {

    sigChan := make(chan os.Signal, 1)

    sigArr := make([]os.Signal, 31)

    for i := range sigArr {

        sigArr[i] = syscall.Signal(i + 0x22)

    }

    signal.Notify(sigChan, sigArr...)

    return sigChan

}


func main() {

    c := getSIGRTchannel()

    // Block until a signal is received.

    for {

        s := <-c

        fmt.Println("Got signal:", s)

    }

}

要使用它,请在一个终端窗口中运行该程序并从另一个终端窗口向它发送一些信号。


查看完整回答
反对 回复 2022-06-13
  • 2 回答
  • 0 关注
  • 175 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号