golang實現子程式通訊

youou發表於2021-09-09

裡用ping程式為例,在main函式中建立ping程式,然後將ping的執行結果透過管道(pipe)傳遞給主程式.主程式讀取結果,然後列印,最後透過主程式傳送系統訊號(syscall.Signal)來結束ping.

    cmd1 := exec.Command("ping", "")      //建立子程式
    ppReader, err := cmd1.StdoutPipe()            //建立管道,ppReader為io.ReaderCloser型別
    var bufReader = bufio.NewReader(ppReader)     //建立帶緩衝的Reader
    if err != nil {
        fmt.Printf("create cmd stdoutpipe failed,error:%sn", err)
        os.Exit(1)
    }
    err = cmd1.Start()   //啟動cmd1
    if err != nil {
        fmt.Printf("cannot start cmd1,error:%sn", err)
        os.Exit(1)
    }

建立協程讀取輸出透過管道傳輸的資料

    go func() {
        var buffer []byte = make([]byte, 4096)        for {
            n, err := bufReader.Read(buffer)   //讀取資料到buffer中
            if err != nil { 
                if err == io.EOF {      //管道關閉後會出現io.EOF錯誤
                    fmt.Printf("pipi has Closedn")                    break
                } else {
                    fmt.Println("Read content failed")
                }
            }
            fmt.Print(string(buffer[:n]))
        }
    }()

主程式傳送訊號給子程式,停止cmd1的執行

    time.Sleep(10 * time.Second)      //讓子程式執行10秒
    err = stopProcess(cmd1)      //    停止子程式
    if err != nil {
        fmt.Printf("stop child process failed,error:%s", err)
        os.Exit(1)
    }
    cmd1.Wait()      //能讓cmd1執行到結束,測試stopProcess是否成功,如果沒有stopProcess,程式和子程式會一直執行
    time.Sleep(1 * time.Second)     //讓協程能讀取關閉子程式時最後一次傳輸的資料

stopProcess的內容

func stopProcess(cmd *exec.Cmd) error {
    pro, err := os.FindProcess(cmd.Process.Pid)     //透過pid獲取子程式
    if err != nil {        return err
    }
    err = pro.Signal(syscall.SIGINT)   //給子程式傳送訊號使之結束
    if err != nil {        return err
    }
    fmt.Printf("結束子程式%s成功n", cmd.Path)    return nil}

完整程式碼段

package main

import (    "bufio"
    "fmt"
    "io"
    "os"
    "os/exec"
    "time"

    "syscall")

func main() {
    cmd1 := exec.Command("ping", "")
    ppReader, err := cmd1.StdoutPipe()
    defer ppReader.Close()
    var bufReader = bufio.NewReader(ppReader)    if err != nil {
        fmt.Printf("create cmd stdoutpipe failed,error:%sn", err)
        os.Exit(1)
    }
    err = cmd1.Start()    if err != nil {
        fmt.Printf("cannot start cmd1,error:%sn", err)
        os.Exit(1)
    }
    go func() {
        var buffer []byte = make([]byte, 4096)        for {
            n, err := bufReader.Read(buffer)            if err != nil {                if err == io.EOF {
                    fmt.Printf("pipi has Closedn")                    break
                } else {
                    fmt.Println("Read content failed")
                }
            }
            fmt.Print(string(buffer[:n]))
        }
    }()
    time.Sleep(10 * time.Second)
    err = stopProcess(cmd1)    if err != nil {
        fmt.Printf("stop child process failed,error:%s", err)
        os.Exit(1)
    }
    cmd1.Wait()
    time.Sleep(1 * time.Second)
}

func stopProcess(cmd *exec.Cmd) error {
    pro, err := os.FindProcess(cmd.Process.Pid)    if err != nil {        return err
    }
    err = pro.Signal(syscall.SIGINT)    if err != nil {        return err
    }
    fmt.Printf("結束子程式%s成功n", cmd.Path)    return nil}

執行結果:

PING  (180.97.33.107) 56(84) bytes of data.64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=1 ttl=55 time=35.3 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=2 ttl=55 time=34.7 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=3 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=4 ttl=55 time=39.6 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=5 ttl=55 time=34.4 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=6 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=7 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=8 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=9 ttl=55 time=34.2 ms64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=10 ttl=55 time=34.2 ms
結束子程式/bin/ping成功

---  ping statistics ---10 packets transmitted, 10 received, 0% packet loss, time 9012ms
rtt min/avg/max/mdev = 34.206/34.967/39.689/1.632 ms
pipi has Closed

Process finished with exit code 0



作者:我的飯卡呢
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4729/viewspace-2819950/,如需轉載,請註明出處,否則將追究法律責任。

相關文章