首页 > 其他分享 >管道(Pipe)

管道(Pipe)

时间:2022-11-15 11:14:31浏览次数:32  
标签:nil err fmt Printf Pipe 管道 Error

管道(pipe)是一种半双工的(或者说是单向的)通讯方式,它只能被用于父进程和子进程以及同祖先的子进程之间的通讯。

使用管道需注意以下四种情况:

  • 如果所有指向管道写端的文件描述符都关闭了,仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。
  • 如果有指向管道写端的文件描述符没关闭,持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
  • 如果所有指向管道读端的文件描述符都关闭了,这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
  • 如果有指向管道读端的文件描述符没关闭,持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

匿名管道

原理类似ps aux | grep java

package main

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

func Ma() {
	cmd1 := exec.Command("ps", "aux")
	cmd2 := exec.Command("grep", "apipe")

	//cmd对象的底层,Stdout与Stdin属性也是通过指向一个字节流实现读写的,这里用新建的字节流代替
	var outputBuf1 bytes.Buffer
	cmd1.Stdout = &outputBuf1
	if err := cmd1.Start(); err != nil {
		fmt.Printf("Error: The first command can not be startup %s\n", err)
		return
	}
	if err := cmd1.Wait(); err != nil { //wait会阻塞cmd直到其运行完毕
		fmt.Printf("Error: Couldn't wait for the first command: %s\n", err)
		return
	}
    
	//cmd1的输出与cmd2的输入指向同一个字节流地址
	cmd2.Stdin = &outputBuf1
	var outputBuf2 bytes.Buffer
	cmd2.Stdout = &outputBuf2
	if err := cmd2.Start(); err != nil {
		fmt.Printf("Error: The second command can not be startup: %s\n", err)
		return
	}
	if err := cmd2.Wait(); err != nil {
		fmt.Printf("Error: Couldn't wait for the second command: %s\n", err)
		return
	}
}

命名管道

原理类似mkfifo -m 777 myfifo cat src.log > myfifo

操作 作用 特性
reader, writer, err := os.Pipe() 创建独立管道 可以被多路复用,不提供原子操作支持
package main

import (
	"fmt"
	"os"
	"time"
)

func Ma() {
	reader, writer, err := os.Pipe()
	if err != nil {
		fmt.Printf("Error: Couldn't create the named pipe: %s\n", err)
	}
	//Read与Write会在另一端还未就绪时对进程进行阻塞,所以二者需要并发运行
	go func() {
		output := make([]byte, 100)
		n, err := reader.Read(output) //会阻塞,等待writer写入
		if err != nil {
			fmt.Printf("Error: Couldn't read data from the named pipe: %s\n", err)
		}
		fmt.Printf("读到了 %d byte(s). [file-based pipe]\n", n)
	}()
	input := make([]byte, 26)
	for i := 65; i <= 90; i++ {
		input[i-65] = byte(i)
	}
	n, err := writer.Write(input) //往管道中写入数据
	if err != nil {
		fmt.Printf("Error: Couldn't write data to the named pipe: %s\n", err)
	}
	fmt.Printf("写入了 %d byte(s). [file-based pipe]\n", n)
	time.Sleep(1 * time.Hour)
}
操作 作用 特性
reader, writer := io.Pipe() 创建内存独立管道 基于内存的提供原子操作保证的管道
package main

import (
	"fmt"
	"io"
	"time"
)

func Ma() {
	reader, writer := io.Pipe()
	go func() {
		output := make([]byte, 100)
		n, err := reader.Read(output)
		if err != nil {
			fmt.Printf("Error: Couldn't read data from the named pipe: %s\n", err)
		}
		fmt.Printf("读到了 %d byte(s). [内存中的管道]\n", n)
	}()
	input := make([]byte, 26)
	for i := 65; i <= 90; i++ {
		input[i-65] = byte(i)
	}
	n, err := writer.Write(input)
	if err != nil {
		fmt.Printf("Error: Couldn't write data to the named pipe: %s\n", err)
	}
	fmt.Printf("写入了 %d byte(s). [内存中的管道]\n", n)
	time.Sleep(200 * time.Millisecond)
}

标签:nil,err,fmt,Printf,Pipe,管道,Error
From: https://www.cnblogs.com/hexug/p/16891716.html

相关文章

  • Linux基础11 重定向(输入重定向,输出重定向); 管道技术, tee, xargs
    1.重定向 将原本要输出到屏幕上的内容,重新指向一个文件或者设备中,屏幕上不会输出原本的内容。为什么要使用重定向: 1.当屏幕输出的信息很重要,而且希望保存重要的信息时。 ......
  • 进程间通信-信号-pipe-fifo
    一、管道(pipe)1、管道的定义和特点管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifopipepipe只能用于有血缘关系的进程进行单向通信。调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过fd......
  • 进程间通信-信号-pipe-fifo
    1.信号signal1、信号的名字和编号:每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIO”、“SIGCHLD”等等。信号定义在signal.h头文件中,信号名都定义为正......
  • 进程间通信-信号-pipe-fifo
    一、有名管道FIFO1.在有名管道(namedpipe或FIFO)提出后,管道(pipe)限制得到了克服。值得注意的是,FIFO严格遵循先进先出(firstinfirstout),对管道及FIFO的读总是从开始处返回......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifo有名管道FIFO无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(namedpipe或FIFO)提出后,该限制得到了克......
  • 进程间通信-信号-pipe-fifo
     任务详情编译运行附件中的代码,提交运行结果截图理解代码,特别是相关系统调用的使用。Linux进程间通信进程是程序运行资源分配的最小单位。每个进程各自有不同的用户......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifo一、fifo1testmf.c——创建一个fifo2producer/consumer生产者和消费者二、pipe1pipe.c获取参数,执行命令2pipedemo.c获取键盘输......
  • 进程间通信-信号-pipe-fifo
    一、有名管道(FIFO)相关概念FIFO(Firstin,Firstout)为一种特殊的文件类型,它在文件系统中有对应的路径。当一个进程以读的方式打开该文件,而另一个进程以写的方式打开该......
  • 进程间通信-信号-pipe-fifo
    fifo管道在有名管道(namedpipe或FIFO)提出后,管道(pipe)限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FI......