什么是命名管道?
Posted
技术标签:
【中文标题】什么是命名管道?【英文标题】:What are named pipes? 【发布时间】:2010-09-15 14:11:01 【问题描述】:它们是什么以及它们是如何工作的?
上下文恰好是 SQL Server
【问题讨论】:
这也是一个很全面的回答:askubuntu.com/questions/449132/… 【参考方案1】:在 Windows 和 POSIX 系统上,命名管道都提供了一种在同一台机器上运行的进程之间进行进程间通信的方式。命名管道为您提供了一种发送数据的方法,而不会因涉及网络堆栈而降低性能。
就像您有一个服务器监听传入请求的 IP 地址/端口一样,服务器也可以设置一个命名管道来监听请求。在任何一种情况下,客户端进程(或 DB 访问库)都必须知道发送请求的具体地址(或管道名称)。通常,存在一个常用的标准默认值(很像 HTTP 的端口 80,SQL 服务器在 TCP/IP 中使用端口 1433;\\.\pipe\sql\query 用于命名管道)。
通过设置额外的命名管道,您可以运行多个数据库服务器,每个服务器都有自己的请求侦听器。
命名管道的优势在于它通常更快,并且可以释放网络堆栈资源。
-- 顺便说一句,在 Windows 世界中,您还可以将命名管道连接到远程机器——但在这种情况下,命名管道是通过 TCP/IP 传输的,因此您将失去性能。使用命名管道进行本地机器通信。
【讨论】:
有什么缺点? @lindhe 没有跨网络的自动可操作性。在实践中一般较难设置。 Windows 中的实现与 Unix/类 Unix 系统中的不同。它们很酷,但除非性能是必须的,否则我不会打扰。【参考方案2】:Unix 和 Windows 都有称为“命名管道”的东西,但它们的行为不同。在 Unix 上,命名管道是一条单向街道,通常只有一个读取器和一个写入器 - 写入器写入,读取器读取,你明白吗?
在 Windows 上,称为“命名管道”的东西是一个 IPC 对象,更像是一个 TCP 套接字 - 东西可以双向流动,并且有一些元数据(您可以在另一端获取该东西的凭据等)。
Unix 命名管道作为文件系统中的一个特殊文件出现,可以通过包括 shell 在内的普通文件 IO 命令访问。 Windows 没有,需要通过特殊的系统调用打开(之后它们的行为与普通的 win32 句柄类似)。
更令人困惑的是,Unix 有一个叫做“Unix 套接字”或 AF_UNIX 套接字的东西,它的工作方式更像(但不完全像)win32“命名管道”,是双向的。
【讨论】:
【参考方案3】:Linux 管道 先进先出(FIFO)进程间通信机制。
未命名管道 在命令行上,用“|”表示两个命令之间。
命名管道 FIFO 特殊文件。创建后,您可以像使用普通文件一样使用管道(打开、关闭、写入、读取等)。
从命令行(man page)创建一个名为“myPipe”的命名管道:
mkfifo myPipe
从 c 创建一个命名管道,其中“路径名”是您希望管道拥有的名称,“模式”包含您希望管道拥有的权限 (man page):
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
【讨论】:
“你可以像使用普通文件一样使用管道” - 不完全正确。你既不能tell()
定位也不能seek()
在管道中。【参考方案4】:
根据Wikipedia:
[...] 传统的管道是“未命名的”,因为它是匿名存在的,并且只在进程运行期间持续存在。命名管道是系统持久的,并且存在于进程生命周期之外,一旦不再使用就必须“取消链接”或删除。进程通常附加到命名管道(通常显示为文件)以执行 IPC(进程间通信)。
【讨论】:
【参考方案5】:比较
echo "test" | wc
到
mkdnod apipe p
wc apipe
wc 会一直阻塞到
echo "test" > apipe
执行
【讨论】:
【参考方案6】:管道是一种在应用程序之间传输数据的方式。在 Linux 下,我一直使用它来将一个进程的输出流式传输到另一个进程。这是匿名的,因为目标应用程序不知道输入流来自哪里。不需要。
named 管道只是一种主动连接到现有管道并收集其数据的方法。它适用于提供者不知道哪些客户将使用数据的情况。
【讨论】:
【参考方案7】:这是来自 Technet 的一个示例(所以不确定为什么标记的答案说命名管道更快??):
命名管道与 TCP/IP 套接字
在快速局域网 (LAN) 环境中,传输控制协议/互联网协议 (TCP/IP) 套接字和命名管道客户端在性能方面具有可比性。但是,TCP/IP 套接字和命名管道客户端之间的性能差异在较慢的网络中变得明显,例如跨广域网 (WAN) 或拨号网络。这是因为进程间通信 (IPC) 机制在对等方之间进行通信的方式不同。
对于命名管道,网络通信通常更具交互性。一个对等点不会发送数据,直到另一个对等点使用读取命令请求它。网络读取通常涉及一系列 peek 命名管道消息,然后才开始读取数据。这些可能在慢速网络中成本非常高,并导致网络流量过大,进而影响其他网络客户端。
澄清您是在谈论本地管道还是网络管道也很重要。如果服务器应用程序在运行 SQL Server 实例的计算机上本地运行,则可以选择本地命名管道协议。本地命名管道在内核模式下运行,速度非常快。
对于 TCP/IP 套接字,数据传输更加流畅,开销也更少。数据传输还可以利用 TCP/IP 套接字性能增强机制,例如窗口化、延迟确认等。这在慢速网络中非常有用。根据应用程序的类型,这种性能差异可能很大。
TCP/IP 套接字也支持积压队列。与在您尝试连接到 SQL Server 时可能导致管道繁忙错误的命名管道相比,这可以提供有限的平滑效果。
通常,TCP/IP 在慢速 LAN、WAN 或拨号网络中是首选,而当网络速度不是问题时,命名管道可能是更好的选择,因为它提供更多功能、易用性和配置选项。
【讨论】:
【参考方案8】:Windows 应用程序的进程间通信(主要是)。类似于在 Unix 中使用套接字在应用程序之间进行通信。
MSDN
【讨论】:
命名管道大约在 1975 年出现在 V6 或 AT&T Unix 中。 噢!这比微软早了一点。据我所知,它们在 Unix/Linux 应用程序中并不经常使用。是吗? 我为我的随机签名生成器使用命名管道 - 因为邮件和 usenet 应用程序希望名为 $HOME/.signature 的文件具有您的签名,所以我的程序将 .signature 创建为命名管道并写入随机引用它。【参考方案9】:unix/linux 上下文中的命名管道可用于使两个不同的 shell 进行通信,因为一个 shell 不能与另一个 shell 共享任何内容。
此外,在同一个 shell 中实例化两次的脚本不能通过这两个实例共享任何内容。在编写包含 start() 和 stop() 函数的守护进程时,我发现了命名管道的用途,并且我想使用相同的脚本来执行这两个操作。
没有命名管道(或任何类型的信号量)在后台启动脚本不是问题。问题是当它完成时,您将无法在后台访问实例。
因此,当您想向他发送停止命令时,您就是不能:在没有命名管道的情况下运行相同的脚本并调用 stop() 函数不会做任何事情,因为您实际上正在运行另一个实例。
解决方案是在您启动守护程序时实现两个管道,一个 READ 和另一个 WRITE。然后让他在其他任务中收听 READ 管道。然后 Stop() 函数包含一个命令,该命令将在管道中写入一条消息,该消息将由执行退出 0 的后台运行脚本处理。这样,同一脚本的第二个实例只需要执行任务:告诉第一个实例停止。
这样,只有一个脚本可以自行启动和停止。
当然,您有不同的方法来做到这一点,例如通过触摸触发停止。但是这个代码很好,也很有趣。
【讨论】:
【参考方案10】:命名管道是用于进程间通信的 Windows 系统。对于 SQL Server,如果服务器与客户端在同一台机器上,则可以使用命名管道来传输数据,而不是 TCP/IP。
【讨论】:
它不是仅限于 Windows 的,因为您的答案会显示出来。正如其他人已经指出的那样,命名管道自 70 年代以来就已在 UNIX 中出现,通常以特殊文件的形式出现。无论如何都赞成,但请修正你的答案。以上是关于什么是命名管道?的主要内容,如果未能解决你的问题,请参考以下文章