151

它们是什么以及它们是如何工作的?

上下文恰好是 SQL Server

4

10 回答 10

166

在 Windows 和 POSIX 系统上,命名管道都提供了一种在同一台机器上运行的进程之间进行进程间通信的方式。命名管道为您提供的是一种发送数据的方法,而不会因涉及网络堆栈而降低性能。

就像您有一个服务器监听传入请求的 IP 地址/端口一样,服务器也可以设置一个可以监听请求的命名管道。在任何一种情况下,客户端进程(或 DB 访问库)都必须知道发送请求的具体地址(或管道名称)。通常,存在一个常用的标准默认值(很像 HTTP 的端口 80,SQL 服务器在 TCP/IP 中使用端口 1433;\\.\pipe\sql\query 用于命名管道)。

通过设置额外的命名管道,您可以运行多个 DB 服务器,每个服务器都有自己的请求侦听器。

命名管道的优点是它通常更快,并且可以释放网络堆栈资源。

-- 顺便说一句,在 Windows 世界中,您也可以将命名管道连接到远程机器 -- 但在这种情况下,命名管道是通过 TCP/IP 传输的,因此您将失去性能。使用命名管道进行本地机器通信。

于 2008-10-06T18:50:14.473 回答
46

Unix 和 Windows 都有称为“命名管道”的东西,但它们的行为不同。在 Unix 上,命名管道是一条单向街道,通常只有一个读取器和一个写入器 - 写入器写入,读取器读取,你明白吗?

在 Windows 上,称为“命名管道”的东西是一个 IPC 对象,更像是一个 TCP 套接字 - 东西可以双向流动,并且有一些元数据(您可以在另一端获取该东西的凭据等)。

Unix 命名管道作为文件系统中的一个特殊文件出现,可以通过包括 shell 在内的普通文件 IO 命令访问。Windows 没有,需要用一个特殊的系统调用打开(之后它们的行为就像一个普通的 win32 句柄)。

更令人困惑的是,Unix 有一个叫做“Unix 套接字”或 AF_UNIX 套接字的东西,它更像(但不完全像)win32“命名管道”,是双向的。

于 2008-10-06T20:51:08.923 回答
25

Linux Pipes
First In First Out (FIFO) 进程间通信机制。

未命名管道
在命令行上,用“|”表示 两个命令之间。

命名管道
FIFO 特殊文件。创建后,您可以像使用普通文件一样使用管道(打开、关闭、写入、读取等)。

要从命令行(手册页)创建名为“myPipe”的命名管道:

mkfifo myPipe  

要从 c 创建命名管道,其中“路径名”是您希望管道拥有的名称,“模式”包含您希望管道拥有的权限(手册页):

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
于 2008-10-06T18:44:04.127 回答
20

根据维基百科

[...] 传统管道是“未命名的”,因为它是匿名存在的,并且仅在进程运行期间持续存在。命名管道是系统持久的,存在于进程生命周期之外,一旦不再使用就必须“取消链接”或删除。进程通常附加到命名管道(通常显示为文件)以执行 IPC(进程间通信)。

于 2008-10-06T18:33:08.173 回答
13

比较

echo "test" | wc

mkdnod apipe p
wc apipe

wc 将阻塞直到

echo "test" > apipe

执行

于 2008-10-06T18:38:24.323 回答
8

管道是一种在应用程序之间传输数据的方式。在 Linux 下,我一直使用它来将一个进程的输出流式传输到另一个进程。这是匿名的,因为目标应用程序不知道输入流来自哪里。它不需要。

命名管道只是一种主动连接到现有管道并收集其数据的方法。它适用于提供者不知道哪些客户将使用数据的情况。

于 2008-10-06T18:33:47.347 回答
8

这是来自 Technet 的一个示例(所以不确定为什么标记的答案说命名管道更快??):

命名管道与 TCP/IP 套接字

在快速局域网 (LAN) 环境中,传输控制协议/Internet 协议 (TCP/IP) 套接字和命名管道客户端在性能方面具有可比性。但是,TCP/IP 套接字和命名管道客户端之间的性能差异在较慢的网络中变得明显,例如跨广域网 (WAN) 或拨号网络。这是因为进程间通信 (IPC) 机制在对等点之间进行通信的方式不同。

对于命名管道,网络通信通常更具交互性。一个对等点不会发送数据,直到另一个对等点使用读取命令请求它。网络读取通常涉及一系列 peek 命名管道消息,然后才开始读取数据。这些在缓慢的网络中可能会非常昂贵,并导致过多的网络流量,进而影响其他网络客户端。

澄清您是在谈论本地管道还是网络管道也很重要。如果服务器应用程序在运行 SQL Server 实例的计算机上本地运行,则可以选择本地命名管道协议。本地命名管道在内核模式下运行,速度非常快。

对于 TCP/IP 套接字,数据传输更加流畅,开销也更少。数据传输还可以利用 TCP/IP 套接字性能增强机制,例如窗口化、延迟确认等。这在慢速网络中非常有用。根据应用程序的类型,这种性能差异可能很大。

TCP/IP 套接字还支持积压队列。与在您尝试连接到 SQL Server 时可能导致管道繁忙错误的命名管道相比,这可以提供有限的平滑效果。

通常,TCP/IP 在慢速 LAN、WAN 或拨号网络中是首选,而当网络速度不是问题时,命名管道可能是更好的选择,因为它提供更多功能、易用性和配置选项。

于 2014-06-03T09:28:41.223 回答
5

Windows 应用程序的进程间通信(主要是)。类似于在 Unix 中使用套接字在应用程序之间进行通信。

MSDN

于 2008-10-06T18:33:43.633 回答
3

unix/linux 上下文中的命名管道可用于使两个不同的 shell 进行通信,因为 shell 不能与另一个 shell 共享任何内容。

此外,在同一个 shell 中实例化两次的脚本不能通过这两个实例共享任何内容。在编写包含 start() 和 stop() 函数的守护程序时,我发现了命名管道的用途,并且我想使用相同的脚本来执行这两个操作。

没有命名管道(或任何类型的信号量)在后台启动脚本不是问题。问题是当它完成时,您将无法在后台访问该实例。

因此,当您想向他发送停止命令时,您不能:在没有命名管道的情况下运行相同的脚本并调用 stop() 函数不会做任何事情,因为您实际上正在运行另一个实例。

解决方案是在启动守护程序时实现两个管道,一个 READ 和另一个 WRITE。然后让他在其他任务中收听 READ 管道。然后 Stop() 函数包含一个命令,该命令将在管道中写入一条消息,该消息将由执行退出 0 的后台运行脚本处理。这样,同一脚本的第二个实例只需要执行任务:告诉第一个实例停止。

这样,只有一个脚本可以自行启动和停止。

当然,您有不同的方法来做到这一点,例如通过触摸触发停止。但是这个代码很好,也很有趣。

于 2011-07-14T04:25:26.530 回答
2

命名管道是用于进程间通信的 Windows 系统。对于 SQL Server,如果服务器与客户端在同一台机器上,则可以使用命名管道来传输数据,而不是使用 TCP/IP。

于 2008-10-06T18:34:13.460 回答