https://github.com/zeromicro/go-zero/blob/master/core/proc/profile.go
自己写代码
我希望接收键盘的输入 同时 键盘也可以杀死它 就是这个程序
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
go func() {
// Go信号通知通过向一个channel发送``os.Signal`来实现。
// 我们将创建一个channel来接受这些通知
//https://pkg.go.dev/os/signal
c := make(chan os.Signal, 1)
signal.Notify(c) //监控全部 一切都是打印处理!
// `signal.Notify`在给定的channel上面注册该channel 可以接受的信号
for { //进到死循环!永远ctrl+c =syscall.SIGINT =打印
sig := <-c //这里只有收通道!只有一半!谁在发?键盘!
fmt.Printf("{sig %#v}{sig.String() %s}", sig, sig.String())
//signal.Reset() //由它无它没啥用 没他更好 由他有时候出问题
//signal.Stop(c) //把前面signal.Notify(c)关闭掉 以后再也监控不到了 ctrl+c会kill程序
//https://pkg.go.dev/syscall#SIGINT 这些值
switch sig { //这里就是if-else 是switch不是select!!
case syscall.SIGINT:
fmt.Println("syscall.SIGINT ctrl+c")
syscall.Kill(os.Getpid(), syscall.SIGKILL) //linux 有 /而WIN没有/测试 可以自杀 参数2使用syscall.SIGINT 自杀未遂
case syscall.SIGKILL:
fmt.Println("syscall.SIGKILL ")//永远可以打印处理 因为不能拦截它
case syscall.SIGTSTP:
fmt.Println("syscall.SIGTSTP ctrl+z")
case syscall.SIGTERM:
fmt.Println("syscall.SIGTERM kill pid")
syscall.Kill(os.Getpid(), syscall.SIGKILL)
default:
fmt.Println("default", sig)
}
}
}()
fmt.Println("awaiting signal pid%d", os.Getpid())
time.Sleep(time.Second * 60)
}
1--基础GO诸塞函数
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan bool)
go func() {
time.Sleep(2 * time.Second)
fmt.Println("send")
done <- true
}()
<-done
fmt.Println("exiting")
}
主程序不是for{}或者time.Sleep毒蛇的
而是通道毒蛇的
2-换成型号
package main
import "fmt"
import "os"
import "os/signal"
import "syscall"
func main() {
// Go信号通知通过向一个channel发送``os.Signal`来实现。
// 我们将创建一个channel来接受这些通知,同时我们还用
// 一个channel来在程序可以退出的时候通知我们
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
// `signal.Notify`在给定的channel上面注册该channel
// 可以接受的信号
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
// 这个goroutine阻塞等待信号的到来,当信号到来的时候,
// 输出该信号,然后通知程序可以结束了
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
// 程序将等待接受信号,然后退出
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
}
win10不能测试
PI可以 ctrl+c可以退出程序 或者 kill -2 -XXX 其中XXX需要自己找出来
ps -aux | grep main
可以找到它的ID
3--解释信号
syscall package - syscall - pkg.go.dev
发送信号
kill -SIGKILL PID
信号处理
通过kill命令给正在运行的程序发送信号
不处理的话,程序会panic处理
Signal handler可以通过signal()系统调用进行设置。如果没有设置,缺省的handler会被调用,当然进程也可以设置忽略此信号。
有两种信号不能被拦截和处理:SIGKILL和SIGSTOP
当接收到信号时,进程会根据信号的响应动作执行相应的操作,信号的响应动作有以下几种:
中止进程(Term)
忽略信号(Ign)
中止进程并保存内存信息(Core)
停止进程(Stop)
继续运行进程(Cont)
用户可以通过signal或sigaction函数修改信号的响应动作(也就是常说的“注册信号”)。另外,在多线程中,各线程的信号响应动作都是相同的,不能对某个线程设置独立的响应动作。
信号介绍
Ctrl-C 发送 INT signal (SIGINT),通常导致进程结束
Ctrl-Z 发送 TSTP signal (SIGTSTP); 通常导致进程挂起(suspend)
Ctrl- 发送 QUIT signal (SIGQUIT); 通常导致进程结束 和 dump core.
Ctrl-T (不是所有的UNIX都支持) 发送INFO signal (SIGINFO); 导致操作系统显示此运行命令的信息
个平台的信号定义或许有些不同。下面列出了POSIX中定义的信号。
Linux 使用34-64信号用作实时系统中。
命令man 7 signal提供了官方的信号介绍。
效果:ctrl+c 可以退出
root@raspberrypi:/home/pi# ./main
awaiting signal
^C
interrupt
exiting
代码分析 Notify 好像是一个不定长参数的函数 可以在后面注册多个信息 而第一个是接受的chan
已经知道
Ctrl-C 发送 INT signal (SIGINT),-----2
Ctrl-Z 发送 TSTP signal (SIGTSTP); -----20
Ctrl- 发送 QUIT signal (SIGQUIT); -----3
修改为:
signal.Notify(sigs, os.Signal(2), os.Signal(3),os.Signal(20))
必须墙砖 否则
墙砖也不行
syscall package - syscall - pkg.go.dev
自己修改一下
signal.Notify(sigs, syscall.Signal(2), syscall.Signal(3), syscall.Signal(20))
可以!!!
run
测试成功
显示屏的PI不能按键盘测试 因为只有C=2可以发出去
测试办法是SSH去发KILL -2 3 20可以看到-----INPUT----其他没有
signal package - os/signal - pkg.go.dev
框框官方的example
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
// Block until a signal is received.
s := <-c
fmt.Println("Got signal:", s)
}
也即是只是监听一个INT 就是2 的效果
参考:os package - os - pkg.go.dev 定义的 var
var ( Interrupt Signal = syscall.SIGINT Kill Signal = syscall.SIGKILL )
好了 到这里可以任意发射炮弹了
signal.Notify(sigs, syscall.Signal(30), syscall.Signal(31))
可以kill -30 -31 ###



