非常教程

Go参考手册

os

os/signal

  • import "os/signal"
  • Overview
  • Index
  • Examples

概观

封装信号实现对输入信号的访问。

信号主要用于类 Unix 系统。有关在 Windows 和 Plan 9上使用此软件包的信息,请参见下文。

Types of signals

信号 SIGKILL 和 SIGSTOP 可能不会被程序捕获,因此不会受此软件包影响。

同步信号是由程序执行中的错误触发的信号:SIGBUS,SIGFPE和SIGSEGV。这些只在程序执行时才被认为是同步的,而不是在使用 os.Process.Kill 或 kill 程序或类似的机制发送时。一般来说,除了如下所述,Go 程序会将同步信号转换为运行时恐慌。

其余信号是异步信号。它们不是由程序错误触发的,而是从内核或其他程序发送的。

在异步信号中,SIGHUP 信号在程序失去其控制终端时发送。当控制终端的用户按下中断字符(默认为^ C(Control-C))时,发送 SIGINT 信号。当控制终端的用户按下退出字符时发送 SIGQUIT 信号,默认为^ \(Control-Backslash)。一般情况下,您可以通过按^ C来使程序简单地退出,并且可以通过按^使堆栈转储退出。

Go程序中信号的默认行为

默认情况下,同步信号被转换为运行时恐慌。SIGHUP,SIGINT或SIGTERM信号导致程序退出。SIGQUIT,SIGILL,SIGTRAP,SIGABRT,SIGSTKFLT,SIGEMT或SIGSYS信号会导致程序以堆栈转储退出。SIGTSTP,SIGTTIN或SIGTTOU信号获取系统默认行为(这些信号由外壳用于作业控制)。SIGPROF信号由 Go 运行时直接处理以实现 runtime.CPUProfile 。其他信号将被捕获,但不会采取任何行动。

如果 Go 程序以忽略 SIGHUP 或 SIGINT(信号处理程序设置为 SIG_IGN)启动,它们将保持忽略。

如果 Go 程序是以非空信号掩码开始的,那么通常将会受到尊重。然而,一些信号被明确地解除阻碍:在GNU / Linux上,同步信号,SIGILL,SIGTRAP,SIGSTKFLT,SIGCHLD,SIGPROF和信号32(SIGCANCEL)和33(SIGSETXID)(SIGCANCEL和SIGSETXID由glibc内部使用)。由 os.Exec 或 os / exec包启动的子进程将继承修改的信号掩码。

改变Go程序中的信号行为

这个包中的函数允许程序改变 Go 程序处理信号的方式。

通知会禁用给定的一组异步信号的默认行为,而是通过一个或多个注册的通道传递它们。具体来说,它适用于信号SIGHUP,SIGINT,SIGQUIT,SIGABRT和SIGTERM。它也适用于作业控制信号SIGTSTP,SIGTTIN和SIGTTOU,在这种情况下系统默认行为不会发生。它也适用于一些不会引起任何动作的信号:SIGUSR1,SIGUSR2,SIGPIPE,SIGALRM,SIGCHLD,SIGCONT,SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGWINCH,SIGIO,SIGPWR,SIGSYS,SIGINFO,SIGTHR,SIGWAITING,SIGLWP,SIGFREEZE, SIGTHAW,SIGLOST,SIGXRES,SIGJVM1,SIGJVM2以及系统中使用的任何实时信号。请注意,并非所有这些信号都适用于所有系统。

如果程序在忽略 SIGHUP 或 SIGINT 的情况下启动,并且任何一个信号都会调用 Notify,则将为该信号安装一个信号处理程序,并且不会再被忽略。如果稍后为该信号调用 Reset 或 Ignore,或者在传递给 Notify 的所有通道上调用 Stop 以获取该信号,则信号将再次被忽略。重置将恢复信号的系统默认行为,而忽略会导致系统完全忽略信号。

如果程序以非空信号掩码开始,则一些信号将如上所述被明确地解除阻塞。如果 Notify 被呼叫阻塞信号,它将被解除阻塞。如果稍后对该信号调用 Reset,或者在传递给 Notify 的所有通道上调用 Stop,则该信号将再次被阻止。

SIGPIPE

当一个 Go 程序写入一个损坏的管道时,内核将产生一个 SIGPIPE 信号。

如果程序尚未调用 Notify 来接收 SIGPIPE 信号,则行为取决于文件描述符编号。在文件描述符1或2(标准输出或标准错误)上写入损坏的管道将导致程序以 SIGPIPE 信号退出。在某些其他文件描述符上写入损坏的管道将不会对 SIGPIPE 信号采取任何操作,并且写入操作将失败并显示 EPIPE 错误。

如果程序调用 Notify 来接收 SIGPIPE 信号,则文件描述符号码无关紧要。SIGPIPE 信号将被传送到通知通道,并且写入将失败并出现 EPIPE 错误。

这意味着,默认情况下,命令行程序的行为与典型的 Unix 命令行程序相同,而其他程序在写入封闭网络连接时不会因 SIGPIPE 而崩溃。

转到使用cgo或SWIG的程序

在包含非 Go 代码(通常使用cgo或SWIG访问的C / C ++代码)的Go程序中,Go 的启动代码通常首先运行。它在非运行启动代码运行之前,按照 Go 运行时的预期配置信号处理程序。如果 non-Go 启动代码希望安装自己的信号处理程序,则必须采取一定步骤才能保证Go运行正常。本节介绍这些步骤,以及 Go-Go 程序对信号处理器设置的整体效果变化。在极少数情况下,非 Go 代码可能在 Go 代码之前运行,在这种情况下,下一节也适用。

如果 Go 程序调用的非 Go 代码不会更改任何信号处理程序或掩码,则行为与纯 Go 程序的行为相同。

如果 non-Go 代码安装任何信号处理程序,则必须在 sigaction 中使用 SA_ONSTACK 标志。如果没有收到信号,很可能会导致程序崩溃。Go 程序通常使用有限的堆栈运行,因此设置了一个备用信号堆栈。另外,Go 标准库期望任何信号处理程序都将使用 SA_RESTART 标志。否则可能会导致某些库调用返回“中断的系统调用”错误。

如果 non-Go 代码为任何同步信号(SIGBUS,SIGFPE,SIGSEGV)安装信号处理程序,则应该记录现有的 Go 信号处理程序。如果这些信号在执行 Go 代码时发生,它应该调用 Go 信号处理程序(无论执行 Go 信号时发生的信号是否可以通过查看传递给信号处理程序的 PC 来确定)。否则,某些 Go 运行时恐慌不会按预期发生。

如果 non-Go 代码为任何异步信号安装信号处理程序,则它可以调用Go信号处理程序或不按照它选择的方式。当然,如果它不调用 Go 信号处理程序,则上述 Go 行为不会发生。这可能是 SIGPROF 信号的问题。

非 Go 代码不应该改变 Go 运行时创建的任何线程上的信号掩码。如果 non-Go 代码自己启动新线程,它可以根据需要设置信号掩码。

如果 non-Go 代码启动一个新线程,更改信号掩码,然后调用该线程中的 Go 函数,则 Go 运行时将自动解除某些信号的阻塞:同步信号SIGILL SIGTRAP SIGSTKFLT SIGCHLD SIGPROF SIGCANCEL和SIGSETXID。当 Go 函数返回时,非 Go 信号掩码将被恢复。

如果 Go 信号处理程序是在未运行 Go 代码的非 Go 线程上调用的,则处理程序通常会将该信号转发给非 Go 代码,如下所示。如果信号是 SIGPROF,则 Go 处理程序不执行任何操作。否则,Go 处理程序会自行删除,解除阻塞信号并再次提升,以调用任何非 Go 处理程序或缺省系统处理程序。如果程序没有退出, Go 处理程序会自行重新安装并继续执行程序。

非Go程序调用Go代码

当 Go 代码使用诸如-buildmode = c-shared之类的选项构建时,它将作为现有非 Go 程序的一部分运行。非 Go 代码在 Go 代码开始时可能已经安装了信号处理程序(当使用 cgo 或 SWIG 时,这种情况也会发生在特殊情况下;在这种情况下,这里的讨论适用)。对于-buildmode = c-archive,Go 运行时将在全局构造函数时初始化信号。对于-buildmode = c-shared,Go 运行时将在共享库加载时初始化信号。

如果 Go 运行时发现 SIGCANCEL 或 SIGSETXID 信号(仅用于GNU / Linux)的现有信号处理程序,它将打开 SA_ONSTACK 标志,否则保持信号处理程序。

对于同步信号和 SIGPIPE,Go 运行时将安装一个信号处理程序。它将保存任何现有的信号处理程序。如果同步信号在执行非 Go 代码时到达,Go 运行时将调用现有的信号处理程序而不是 Go 信号处理程序。

使用-buildmode = c-archive或-buildmode = c-shared构建的Go代码默认情况下不会安装任何其他信号处理程序。如果存在现有的信号处理程序,Go 运行时将打开 SA_ONSTACK 标志,否则保持信号处理程序。如果 Notify 被调用为异步信号,则会为该信号安装 Go 信号处理程序。如果稍后对该信号调用 Reset,则将重新安装该信号的原始处理,如果有的话还原非 Go 信号处理程序。

不使用-buildmode = c-archive或-buildmode = c-shared构建的 Go 代码将为上面列出的异步信号安装信号处理程序,并保存任何现有的信号处理程序。如果一个信号被传送到一个非 Go 线程,它将按照上面描述的方式工作,除了如果有一个现有的非 Go 信号处理程序,该处理程序将在提升信号之前被安装。

Windows

在 Windows 上,^ C(Control-C)或^ BREAK(Control-Break)通常会导致程序退出。如果通知被调用 os.Interrupt , ^ C 或 ^ BREAK 将导致 os.Interrupt 在通道上发送,并且程序不会退出。如果调用Reset,或在传递给 Notify 的所有通道上调用 Stop,则将恢复默认行为。

Plan 9

在计划9中,信号具有类型 syscall.Note,这是一个字符串。使用 syscall.Note 调用通知将导致该值在通道上发送,当该字符串发布为备注时。

Index

  • func Ignore(sig ...os.Signal)
  • func Notify(c chan<- os.Signal, sig ...os.Signal)
  • func Reset(sig ...os.Signal)
  • func Stop(c chan<- os.Signal)

例子

Notify

包文件

doc.go signal.go signal_unix.go

func Ignore(显示源文件)

func Ignore(sig ...os.Signal)

忽略导致提供的信号被忽略。如果他们被程序收到,什么都不会发生。忽略任何先前通知提供的信号通知的效果。如果没有提供信号,则所有输入信号都将被忽略。

func Notify(显示源文件)

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

通知会导致软件包信号将输入信号中继到 c 。如果没有提供信号,所有输入信号将被中继到 c 。否则,只有提供的信号会。

包信号不会阻止发送到 c:调用者必须确保 c 有足够的缓冲空间来跟上预期的信号速率。对于仅用于通知一个信号值的通道,大小为1的缓冲区就足够了。

允许使用相同的频道多次调用通知:每个呼叫都会扩展发送到该频道的一组信号。从集合中删除信号的唯一方法是调用 Stop 。

可以使用不同的通道和相同的信号多次呼叫通知:每个通道独立接收输入信号的副本。

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)
}

func Reset(显示源文件)

func Reset(sig ...os.Signal)

重设撤消任何先前呼叫的效果,以通知所提供的信号。如果没有提供信号,所有信号处理程序将被重置。

func Stop(显示源文件)

func Stop(c chan<- os.Signal)

停止导致封装信号停止将输入信号中继到 c 。它解除了以前使用 c 通知通知的效果。当停止返回时,保证 c 将不会收到更多信号。

Go

Go 是一种编译型语言,它结合了解释型语言的游刃有余,动态类型语言的开发效率,以及静态类型的安全性。它也打算成为现代的,支持网络与多核计算的语言。要满足这些目标,需要解决一些语言上的问题:一个富有表达能力但轻量级的类型系统,并发与垃圾回收机制,严格的依赖规范等等。这些无法通过库或工具解决好,因此Go也就应运而生了。

主页 https://golang.org/
源码 https://go.googlesource.com/go
发布版本 1.9.2

Go目录

1.档案 | archive
2.缓冲区 | bufio
3.内置 | builtin
4.字节 | bytes
5.压缩 | compress
6.容器 | container
7.上下文 | context
8.加密 | crypto
9.数据库 | database
10.调试 | debug
11.编码 | encoding
12.错误 | errors
13. expvar
14.flag
15. fmt
16. go
17.散列 | hash
18.html
19.图像 | image
20.索引 | index
21.io
22.日志 | log
23.数学 | math
24. math/big
25.math/bits
26.math/cmplx
27.math/rand
28.拟态 | mime
29.net
30.net/http
31. net/mail
32. net/rpc
33.net/smtp
34. net/textproto
35. net/url
36.os
37.路径 | path
38.插件 | plugin
39.反射 | reflect
40.正则表达式 | regexp
41.运行时 | runtime
42.排序算法 | sort
43.转换 | strconv
44.字符串 | strings
45.同步 | sync
46.系统调用 | syscall
47.测试 | testing
48.文本 | text
49.时间戳 | time
50.unicode
51.不安全性 | unsafe
52.Go 语言数据类型
53.Go 语言基础语法
54.Go 语言结构
55.Go 语言 select 语句
56.Go 语言 switch 语句
57.Go 语言 if 语句嵌套
58.Go 语言 if…else 语句
59.Go 语言 if 语句
60.Go 语言运算符
61.Go 语言常量
62.Go 语言函数闭包
63.Go 语言函数作为实参
64.Go 语言函数引用传递值
65.Go 语言函数值传递值
66.Go 语言函数
67.Go 语言 goto 语句
68.Go 语言 continue 语句
69.Go 语言 break 语句
70.Go 语言循环嵌套
71.Go 语言 for 循环
72.Go 语言结构体
73.Go 语言指针作为函数参数
74.Go 语言指向指针的指针
75.Go 语言指针数组
76.Go 语言指针
77.Go 语言向函数传递数组
78.Go 语言多维数组
79.Go 语言变量作用域
80.Go 语言函数方法
81.Go 错误处理
82.Go 语言接口
83.Go 语言类型转换
84.Go 语言递归函数
85.Go 语言Map(集合)
86.Go 语言范围(Range)
87.Go 语言切片(Slice)
88.Go 并发
89.Go fmt.Sprintf 格式化字符串