golang实现并发子进程通信(实例)

这里用ping进程为例,在main函数中创建一个并发ping程序,然后将ping的执行结果通过管道(pipe)传递给主程序,主程序读取结果,然后打印,最后通过主程序发送系统信号(syscall.Signal)来结束ping。

创建子进程(并发 用IO口进行通信 走二进制码流)

 cmd1 := exec.Command("ping", "www.baidu.com")      //创建子进程
    ppReader, err := cmd1.StdoutPipe()            
    			//创建管道,ppReader为io.ReaderCloser类型
    			
    var bufReader = bufio.NewReader(ppReader)     //创建带缓冲的Reader
    
    if err != nil {
        fmt.Printf("create cmd stdoutpipe failed,error:%s\n", err)
        os.Exit(1)            // 中断整个程序  属于异常处理
    }
    
    err = cmd1.Start()   //启动cmd1
    if err != nil {
        fmt.Printf("cannot start cmd1,error:%s\n", 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 Closed\n")
                    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", "www.baidu.com")
    ppReader, err := cmd1.StdoutPipe()
    defer ppReader.Close()
    var bufReader = bufio.NewReader(ppReader)
    if err != nil {
        fmt.Printf("create cmd stdoutpipe failed,error:%s\n", err)
        os.Exit(1)
    }
    err = cmd1.Start()
    if err != nil {
        fmt.Printf("cannot start cmd1,error:%s\n", 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 Closed\n")
                    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 www.a.shifen.com (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 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=2 ttl=55 time=34.7 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=3 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=4 ttl=55 time=39.6 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=5 ttl=55 time=34.4 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=6 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=7 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=8 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=9 ttl=55 time=34.2 ms
64 bytes from 180.97.33.107 (180.97.33.107): icmp_seq=10 ttl=55 time=34.2 ms
结束子进程/bin/ping成功

--- www.a.shifen.com 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

你可能感兴趣的:(golang)