- https://bindog.github.io/blog/2014/09/25/pipes-and-filters/">https://bindog.github.io/blog/2014/09/25/pipes-and-filters/
- https://zhuanlan.zhihu.com/p/58489873">https://zhuanlan.zhihu.com/p/58489873
- https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(Unix))">https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(Unix))
- https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(%E8%BD%AF%E4%BB%B6))">https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(%E8%BD%AF%E4%BB%B6))
https://bindog.github.io/blog/2014/09/25/pipes-and-filters/
0x01 执行流程
0x02 性能和复杂度
如果其中某些进程执行的是复杂的计算任务,那么它们将自动在多处理器上并行执行。这么来看的话管道的优势非常明显~
0x03 异常
这就是传统的Unix管道一个非常大的缺点,如果想在管道处理数据时探测异常需要用到带外数据(out-of-band)信号来检测异常,并将消息发到其他进程(如果你的过滤器有不止一个输入管道这是非常好实现的,但如果你使用的仅仅是Unix管道就比较困难了)
比如当某个用户使用了Eric Idle这个用户名或者填写了一个不存在的organization时,我们如何reject这次提交并告知用户错误信息呢?一个非常有Unix特色的方法就是使用命名管道(named pipe)来处理所有失败请求
mkfifo errors # create a named pipe for our errorsmy_webserver |line_sanitizer 2> errors |verifier 2> errors |pdf_renderer 2> errors
任何进程都可以从我们自定义的命名管道errors中读取数据,此外管道中的每个进程都可以把错误信息输出到命名管道errors中。我们还可以添加一个reader,当发生异常的时候从命名管道errors中读取信息并给我们发一封邮件
0x05 分布式管道
https://zhuanlan.zhihu.com/p/58489873
管道是UNIX环境中历史最悠久的进程间通信方式。
管道本质上就是一个文件,前面的进程以写方式打开文件,后面的进程以读方式打开。这样前面写完后面读,于是就实现了通信。实际上管道的设计也是遵循UNIX的“一切皆文件”设计原则的,它本质上就是一个文件。Linux系统直接把管道实现成了一种文件系统,借助VFS给应用程序提供操作接口。
虽然实现形态上是文件,但是管道本身并不占用磁盘或者其他外部存储的空间。在Linux的实现上,它占用的是内存空间。所以,Linux上的管道就是一个操作方式为文件的内存缓冲区。
管道的分类和使用
Linux上的管道分两种类型:
- 匿名管道
- 命名管道
这两种管道也叫做有名或无名管道。匿名管道最常见的形态就是我们在shell操作中最常用的”|”。它的特点是只能在父子进程中使用,父进程在产生子进程前必须打开一个管道文件,然后fork产生子进程,这样子进程通过拷贝父进程的进程地址空间获得同一个管道文件的描述符,以达到使用同一个管道通信的目的。此时除了父子进程外,没人知道这个管道文件的描述符,所以通过这个管道中的信息无法传递给其他进程。这保证了传输数据的安全性,当然也降低了管道了通用性,于是系统还提供了命名管道。
https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(Unix))
在类Unix操作系统(以及一些其他借用了这个设计的操作系统,如Windows)中,管道(英语:Pipeline)是一系列将标准输入输出链接起来的进程,其中每一个进程的输出被直接作为下一个进程的输入。 每一个链接都由匿名管道实现[来源请求]。管道中的组成元素也被称作过滤程序。
实现[编辑&action=edit§ion=10)]
在大多数类UNIX操作系统中,管线上的所有进程同时启动,输入输出流也已经被正确地连接,并且这些进程被调度程序所管理。最为重要的一点就是,所有的UNIX管道和其他管道实现不一样的地方就是缓存的概念:输出进程可能会以每秒5000 byte的速度输出,但是接收进程也许每秒只能接收100 byte,但不会有数据丢失。原因就是管道上游的进程的所有输出都会被放入一个队列中。当下游进程开始接收数据时,操作系统就会将数据从队列传至接收进程,并将传完的数据从队列中移除。当缓存队列空间不足时,上游进程会被终止,直到接收进程读取数据为上游进程腾出空间。在Linux中,缓存队列的大小是65536 byte。
网络管线[编辑&action=edit§ion=11)]
根据Unix哲学——“一切都是文件”,[netcat](https://zh.wikipedia.org/wiki/Netcat)和[socat](https://zh.wikipedia.org/w/index.php?title=Socat&action=edit&redlink=1)这样的工具可以将管道连接到TCP/IP套接字。
https://zh.wikipedia.org/wiki/%E7%AE%A1%E9%81%93_(%E8%BD%AF%E4%BB%B6))
管道与过滤器设计模式
管道(pipeline),本源是使用消息传递的进程间通信机制,它构成自链接起来的处理元素(进程、线程、协程和函数等),它们被安置为每个元素的输出都是下一个元素的输入;这个名字类比于物理上的管道运输。在连贯的元素之间,通常会提供一定数量的缓冲区。在管道中流动的信息,经常是记录、字节或位的流(stream),而管道的元素可以叫做过滤器&action=edit&redlink=1)。将元素连接成管道类似于函数复合&action=edit&redlink=1)。在软件工程中,称之为管道与过滤器设计模式[1]#cite_note-1)。
管道和过滤器&action=edit&redlink=1),可以被看作使用字节流作为数据对象的一种形式的函数式编程;更具体的说,它们可以被看作是特定形式的I/O单子)
