栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go操作LINUX 系统信号

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go操作LINUX 系统信号

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 ###

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/904342.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号