我正在使用GO来检查一个进程(不是父进程)是否已终止,基本上类似于FreeBSD中的pwait命令,但用 go 编写。
目前我正在尝试 a for loop
,kill -0
但我注意到这种方法的 CPU 使用率非常高99%,这里是代码:
package main
import (
"fmt"
"os"
"strconv"
"syscall"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s pid", os.Args[0])
os.Exit(1)
}
pid, err := strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
panic(err)
}
process, err := os.FindProcess(int(pid))
err = process.Signal(syscall.Signal(0))
for err == nil {
err = process.Signal(syscall.Signal(0))
time.Sleep(500 * time.Millisecond)
}
fmt.Println(err)
}
关于如何改进或正确实施这一点的任何想法。
提前致谢。
更新
sleep
像建议的那样在循环中添加一个有助于减少负载。
从提供的链接来看,似乎可以附加到现有的 pid,我会尝试PtraceAttach但不知道这是否有副作用,有什么想法吗?
正如建议的那样,我可以使用kqueue:
package main
import (
"fmt"
"log"
"os"
"strconv"
"syscall"
)
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s pid", os.Args[0])
os.Exit(1)
}
pid, err := strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
panic(err)
}
process, _ := os.FindProcess(int(pid))
kq, err := syscall.Kqueue()
if err != nil {
fmt.Println(err)
}
ev1 := syscall.Kevent_t{
Ident: uint64(process.Pid),
Filter: syscall.EVFILT_PROC,
Flags: syscall.EV_ADD,
Fflags: syscall.NOTE_EXIT,
Data: 0,
Udata: nil,
}
for {
events := make([]syscall.Kevent_t, 1)
n, err := syscall.Kevent(kq, []syscall.Kevent_t{ev1}, events, nil)
if err != nil {
log.Println("Error creating kevent")
}
if n > 0 {
break
}
}
fmt.Println("fin")
}
工作正常,但想知道如何在 linux 上实现/实现相同的功能,因为我认为kqueue
它不可用,有什么想法吗?