Answers:
在Windows和POSIX系统上,命名管道都为在同一计算机上运行的进程之间进行进程间通信提供了一种方法。命名管道为您提供了一种发送数据的方式,而不会导致涉及网络堆栈的性能损失。
就像您有一个服务器在侦听IP地址/端口中的传入请求一样,服务器也可以设置一个命名管道来侦听请求。在这两种情况下,客户端进程(或数据库访问库)都必须知道发送请求的特定地址(或管道名称)。通常,存在一个常用的标准默认值(类似于HTTP的端口80,SQL Server在TCP / IP中使用端口1433; \\。\ pipe \ sql \ query用于命名管道)。
通过设置其他命名管道,您可以运行多个数据库服务器,每个服务器都有自己的请求侦听器。
命名管道的优点是通常更快,并释放网络堆栈资源。
-顺便说一句,在Windows世界中,您还可以将命名管道分配到远程计算机上-但是在这种情况下,命名管道是通过TCP / IP传输的,因此您将失去性能。使用命名管道进行本地计算机通信。
Unix和Windows都有所谓的“命名管道”,但是它们的行为有所不同。在Unix上,命名管道是一条单向街道,通常只有一个读者和一个作者-作家写,而读者读,明白吗?
在Windows上,称为“命名管道”的事物是IPC对象,更像TCP套接字-事物可以双向流动并且有一些元数据(您可以在另一端获取事物的凭据,等等)。
Unix命名管道在文件系统中显示为特殊文件,并且可以使用常规文件IO命令(包括外壳程序)进行访问。Windows则不需要,并且需要通过特殊的系统调用来打开(在此之后,它们的行为通常类似于正常的win32句柄)。
更加令人困惑的是,Unix具有一种称为“ Unix套接字”或AF_UNIX套接字的东西,它的工作方式类似于(但不完全像)win32“命名管道”,是双向的。
Linux通过管道进行
先进先出(FIFO)进程间通信机制。
未命名的管道
在命令行上,用“ |”表示 在两个命令之间。
命名管道
FIFO特殊文件。创建管道后,您就可以像正常文件一样使用管道(打开,关闭,写入,读取等)。
要从命令行(手册页)创建一个名为“ myPipe”的命名管道:
mkfifo myPipe
要从c创建命名管道,其中“ pathname”是您希望管道具有的名称,“ mode”包含希望管道具有的权限(手册页):
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
tell()
定位也不能seek()
在管道中。
这是Technet的代表(因此不确定为什么标记的答案显示命名管道更快?):
命名管道与TCP / IP套接字
在快速局域网(LAN)环境中,传输控制协议/ Internet协议(TCP / IP)套接字和命名管道客户端在性能方面是可比的。但是,TCP / IP套接字和命名管道客户端之间的性能差异在较慢的网络(例如跨广域网(WAN)或拨号网络)中变得明显。这是因为进程间通信(IPC)机制在同级之间进行通信的方式不同。
对于命名管道,网络通信通常更具交互性。一个对等方不会发送数据,直到另一个对等方使用读取命令进行请求。网络读取通常在开始读取数据之前涉及一系列窥视的命名管道消息。这些在缓慢的网络中可能会非常昂贵,并导致过多的网络流量,进而影响其他网络客户端。
弄清楚您是在谈论本地管道还是网络管道,也很重要。如果服务器应用程序在运行SQL Server实例的计算机上本地运行,则可以使用本地命名管道协议。本地命名管道以内核模式运行,并且速度非常快。
对于TCP / IP套接字,数据传输更加简化并且开销更少。数据传输还可以利用TCP / IP套接字性能增强机制,例如窗口,延迟确认等。这在网络速度较慢的情况下非常有帮助。根据应用程序的类型,此类性能差异可能会很大。
TCP / IP套接字还支持积压队列。与命名管道相比,这只能提供有限的平滑效果,在您尝试连接到SQL Server时可能导致管道繁忙错误。
通常,TCP / IP在慢速LAN,WAN或拨号网络中是首选,而当网络速度不成问题时,命名管道可能是更好的选择,因为它提供了更多的功能,易用性和配置选项。
Windows应用程序的进程间通信(主要是)。类似于使用套接字在Unix中的应用程序之间进行通信。
Unix / Linux上下文中的命名管道可用于使两个不同的Shell进行通信,因为Shell根本无法与他人共享任何内容。
此外,在同一shell中实例化两次的脚本无法通过两个实例共享任何内容。在对包含start()和stop()函数的守护程序进行编码时,我发现了一种用于命名管道的方法,并且我想使用相同的脚本来执行这两个操作。
如果没有命名管道(或任何种类的信号灯),则在后台启动脚本不是问题。问题是,完成后您将无法在后台访问该实例。
因此,当您想向他发送stop命令时,您将无法执行以下操作:在没有命名管道的情况下运行同一脚本并调用stop()函数将不会执行任何操作,因为您实际上正在运行另一个实例。
解决方案是在启动守护程序时实现两个管道,一个管道读取,另一个管道写入。然后使他以及其他任务听READ管道。然后Stop()函数包含一个将在管道中写入消息的命令,该命令将由后台运行脚本处理,该脚本将执行出口0。这样,同一脚本的第二个实例仅在执行任务时:告诉第一个实例停止。
这样,只有一个脚本可以启动和停止。
当然,您可以通过多种方式来实现此目的,例如通过触摸触发停止。但这是很好的代码。