GOを使用して、プロセス (親ではない) が終了したかどうかを確認しています。基本的には、 FreeBSDのpwaitコマンドのようなものですが、go で記述されています。
for loop
現在、で を試していますが、このアプローチでは CPU 使用率が99%kill -0
と非常に高いことに気付きました。コードは次のとおりです。
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)
}
これを改善または適切に実装する方法についてのアイデア。
前もって感謝します。
アップデート
提案されているようにループ内に a を追加すると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 では利用できないと思うので、Linux で同じことを実装/達成する方法を知りたいのkqueue
ですが、何かアイデアはありますか?