kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -34- <Start>

こんにちは、kurumi-bioです。
第5回目のexecパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20.3 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.1 linux/amd64

Start関数

func (c *Cmd) Start() error

関数の説明Start は、指定されたコマンドを開始しますが、完了するまで待機しません。
Start が正常に返されると、c.Process フィールドが設定されます。
Start の呼び出しが成功した後、関連するシステム リソースを解放するために、Wait メソッドを呼び出す必要があります。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
    "time"
)

func main() {
    c := exec.Command("./sleep.exe", "5")
    n := time.Now()
    fmt.Printf("測定開始: %1.1f 秒経過\n", time.Since(n).Seconds())
    e := c.Start()
    fmt.Printf("Start関数後: %1.1f 秒経過\n", time.Since(n).Seconds())
    if e != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", e)
    }
    e = c.Wait()
    fmt.Printf("Wait関数後: %1.1f 秒経過\n", time.Since(n).Seconds())
    if e != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", e)
    }
}

コードの説明 前回作成したsleep.exeコマンドをCmd.Start()関数を使って実行します。
Cmd.Start()関数後とCmd.Wait()関数後に経過時間を表示しています。

◆実行結果(Windows)

実行結果の説明 Cmd.Run()関数と異なり、Cmd.Start()関数は、即時返ってきました。
Cmd.Wait()関数を呼ぶと、Sleep.exeコマンドの実行完了まで待つことがわかりました。

プログラムを実行したことで、
Cmd.Wait()関数は、実行したコマンドが終了するまで「待つ」ことがわかりました。
本体のプロセスと実行したコマンドが同時に動いていれば、 本体のプロセスの時間が経過すれば、Cmd.Wait()関数の待ち時間も減るか試してみます。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
    "strconv"
    "time"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Println("usage: StartTestK1.exe second")
    }
    i, _ := strconv.Atoi(os.Args[1])
    t := time.Duration(i)
    time.Sleep(t * time.Second)

    c := exec.Command("./sleep.exe", "5")
    e := c.Start()
    if e != nil {
        fmt.Printf("error: %v\n", e)
    }
    time.Sleep(t * time.Second)

    n := time.Now()
    fmt.Printf("測定開始: %1.1f 秒経過\n", time.Since(n).Seconds())
    e = c.Wait()
    fmt.Printf("Wait関数後: %1.1f 秒経過\n", time.Since(n).Seconds())
    if e != nil {
        fmt.Printf("error: %v\n", e)
    }
}

コードの説明 sleep.exeコマンド実行後に、任意の秒数プロセスを停止し、Cmd.Wait()関数の実行時間を測定します。
Cmd.Wait()関数の実行時間が「5秒-プロセス停止時間」になれば、同時に実行していたことになります。

◆実行結果(Windows)

実行結果の説明 Cmd.Wait()関数の実行時間が、5秒-"コマンド実行引数で指定した秒"になっていることが確認できました。
また、プロセスの待機時間がコマンドの実行時間よりも長い場合は、Cmd.Wait()関数が即時終わること後が確認できました。

関数の説明にc.Processフィールドが設定されると記載されています。
このc.Processフィールドの値を出力してみます。

c.Process フィールド

type Process struct {
    Pid int
    // contains filtered or unexported fields
}

説明 Process は、StartProcess によって作成されたプロセスに関する情報を格納します。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func printPid(p *os.Process) {
    if p == nil {
        fmt.Println("Process is nil.")
        return
    }
    fmt.Printf("pid=[%d]\n", p.Pid)
}

func main() {
    c := exec.Command("./sleep.exe", "1")
    printPid(c.Process)

    e := c.Start()
    printPid(c.Process)
    if e != nil {
        fmt.Printf("error: %v\n", e)
    }

    e = c.Wait()
    printPid(c.Process)
    if e != nil {
        fmt.Printf("error: %v\n", e)
    }
}

コードの説明 exec.Command()関数、Cmd.Start()関数およびCmd.Wait()関数を呼んだ後にc.Processフィールドを出力すします。もし、c.Processnilの場合は、"Process is nil."と出力します。

◆実行結果(Windows)

実行結果の説明 Cmd.Start()関数を呼んだ後に、c.Processフィールドが設定されてpidが出力されることが確認できました。

最後までご覧いただきありがとうございます