10

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ですが、何かアイデアはありますか?

4

1 に答える 1