我有以下两个简单的程序。
家长:
package main
import (
"fmt"
"syscall"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
if err != nil {
fmt.Println("Error:", err)
return
}
}
孩子:
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("hi from child")
time.Sleep(time.Second * 5)
}
}
输出ps
:
yakog@yakog-computer:~/goprojects/parent$ ps -o pid,ppid,pgid,uid,wchan,stat,tt,command -t /dev/pts/19
PID PPID PGID UID WCHAN STAT TT COMMAND
1867701 1867320 1867701 1000 do_sel Ss+ pts/19 bash
1870508 2118 1870508 1000 ep_pol Sl pts/19 child
当我按下CTRL-Z
或 时CTRL-C
,它没有任何效果。这正是我所期望的,因为进程 1870508 不是前台作业的一部分,并且CTRL-Z
/CTRL-C
调用kill -SIGTSTP -1867701
/ kill -SIGINT -1867701
。因此,1870508 不会收到这些信号。
另外,当我调用kill -SIGINT 1870508
或 时kill -SIGSTOP 1870508
,进程被终止/暂停。我仍然可以理解。虽然 1870508 不是前台作业的一部分,但使用kill
命令我们“直接”将信号发送给进程。
但是,为什么不起作用kill -SIGTSTP 1870508
?启动./parent
进程并调用kill -SIGTSTP 1870508
命令后,实际上什么都没有发生(1870508 仍然具有状态R
/S
并继续打印到终端)。我不明白为什么它没有暂停进程(将其移动到)。它应该与和T
相同(我们“直接”向进程发送 -SIGTSTP),但是,在这种情况下它没有效果。-SIGINT
-SIGSTOP
奇怪的是,如果我们改变父代码(下面的代码)并使其在子进程创建后继续执行,那么它就kill -SIGTSTP 1870508
可以正常工作(子进程被暂停)。
package main
import (
"fmt"
"os/signal"
"syscall"
"time"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
Sys: &syscall.SysProcAttr{ // child in its own group
Setpgid: true,
Pgid: 0,
},
}
_, err := syscall.ForkExec("./child/child", []string{"child"}, attr)
signal.Ignore(syscall.SIGTSTP)
if err != nil {
fmt.Println("Error:", err)
return
}
for {
fmt.Println("hi from parent")
time.Sleep(time.Second * 7)
}
}
此外,当我调用kill -SIGSTOP 1870508
(将进程移动到T
状态)然后调用kill -SIGINT 1870508
它时,它不会终止进程......为什么?