我正在使用 Linux(ubuntu)。
当我man 7 signal
在终端中输入 (manual 2020-12-21) 时,我发现 SIGCHLD 出现以下情况:
SIGCHLD P1990 Ign Child stopped or terminated
因此,它表明SIGCHLD
仅在这两种情况下才会生成信号。它并未说明子进程何时继续运行。
然而,在 POSIX 中,它规定如下:
SIGCHLD Child process terminated, stopped,
[XSI] or continued.
因此,当 OS 支持 XSI 时,子进程继续时也会生成此信号。我还编写了一些简单的子进程/父进程程序,可以确认这一点。既然 Linux 支持 XSI,为什么手册中不包括 SIGCHLD 的“继续”场景?如果手册不完整(或者我不明白它的用途),那么手册的目的是什么?
此外,我发现以下有关SIGCHLD 的答案不完整。
下面是代码。这是一段简单的 golang 代码。父进程通过经典的 fork/exec 启动子进程。然后它为 SIGCHLD 信号注册一个处理程序,就这样。父进程和子进程每 10 秒打印一条消息。构建两个程序后,我通过命令运行它们。我通过和控制子进程的./parent
行为(T
<->状态) 。R/S
kill -SISTOP child_process_id
kill -SIGCONT child_process_id
家长:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
if err != nil {
fmt.Println("Error:", err)
return
}
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGCHLD)
go func() {
for {
select {
case <-ch:
fmt.Println("SIGNAL")
}
}
}()
for {
fmt.Println("Parent is live")
time.Sleep(10 * time.Second)
}
}
孩子:
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("hi from child")
time.Sleep(time.Second * 10)
}
}
该措辞已在上游 linux-man 存储库中得到修复:
在您的系统上升级 man-pages 包可能需要一些时间,因此您可以克隆开发存储库并在您的系统上获得最新版本的手册页:
要回答问题标题中的“为什么不”,我想说
signal(7)
手册页并不是查找内核使用特定信号的所有方式的综合目录的地方。手册页仅提供每个信号含义的简要描述。这与其他复杂、详细的主题(如gdb(1)和awk)一致,它们的手册页仅以基本的一般术语解释命令和命令行选项。全面深入的介绍留给书籍和大型网站。手册页在信息量和复杂程度方面是有限的。对于简单的命令,手册页就足够了。与计算机中的其他一切一样,手册页也有优点和缺点。它们适合记录某些内容,但不适合记录其他内容。对于信号等操作系统内部信息,它们不够用,而期望手册页能够完整解释所有内容只会让您失望。