命名管道

命名管道是计算机进程间的一种先进先出通信机制。是类Unix系统传统管道的扩展。传统管道属于匿名管道，其生存期不超过创建管道的进程的生存期。但命名管道的生存期可以与操作系统运行期一样长。

Unix

与传统的无名的shell管道不同，命名管道利用了文件系统。使用mkfifo()或mknod()创建命名管道。两个进程可以通过管道的名字打开、读写管道。 
例如，可以创建管道，让gzip压缩管道传给它的数据：
 mkfifo my_pipe
 gzip -9 -c < my_pipe > out.gz &
在另一个进程shell中，独立地发送数据给管道以被压缩： 
cat file > my_pipe
命名管道可如普通文件那样被删除：
rm my_pipe
命名管道可用于从一个进程向另一个进程发送信息而不需使用中间临时文件。例如，gzip解压缩数据可以输出到一个命名管道中： 
 mkfifo -m 0666 /tmp/namedPipe
 gzip -d < file.gz > /tmp/namedPipe
然后把解压缩数据存入MySQL的表中:
 LOAD DATA INFILE '/tmp/namedPipe' INTO TABLE tableName;
如果不使用管道，就需要把解压缩数据完整地保存在文件中以上传到MySQL。
PostgreSQL的命令行工具psql也支持从命名管道装入数据。

Windows操作系统

命名管道可以类似于文件那样，使用Win32 SDK函数CreateFile, ReadFile, WriteFile, CloseHandle打开、读写、关闭。
与Unix不同，在Windows的命令行界面上不能使用命名管道，除了PowerShell终端模拟器。另一点不同是Windows命名管道是易失的，如果对命名管道的引用为0就会自动被关闭。第三点不同是Windows命名管道被安装在命名管道文件系统（named pipe filesystem，NPFS），安装路径是\\.\pipe\。例如管道名字"foo"的全路径名是\\.\pipe\foo)。
匿名管道实际上是采用随机名字的命名管道。 
命名管道可继承安全上下文；可跨计算机做进程间通信；可全双工或半双工通信；可以是面向字节协议或分组交换；可靠通信；阻塞或非阻塞读写；标准设备I/O句柄；可用名字来创建句柄；广域网通信效率低（与TCP/IP滑动窗口相比，使用明确的数据请求）；可窥探式读（读数据但不从输入缓冲区中删除）。 
命名管道可以同时创建多个实例，只要不超过nMaxInstances。一个实例只能连接一个客户端，若想连接其它的客户端，需要先调用DisconnectNamedPipe关闭现有的管道连接。另外创建命名对象时可以为参数dwOpenMode指定FILE_FLAG_FIRST_PIPE_INSTANCE，指定这个参数后，若创建的命名管道对象不是第一个实例，会报错ERROR_ACCESS_DENIED。
.NET Framework 3.5增加了命名管道支持。命名管道可用作Microsoft SQL Server.的客户端点（endpoint）。
命名管道也是服务器讯息区块(SMB)支持的一种网络协议。Windows NT的整个NT Domain服务协议是基于命名管道之上的DCE/RPC服务。Exchange 5.5 Administrative应用也是如此。

例子

//命名管道服务器
    #include <windows.h>  
    #include <stdio.h>  
      
    int main(void)  
    {  
        HANDLE PipeHandle;  
        DWORD BytesRead;  
        CHAR buffer[256];  
      
        if ((PipeHandle = CreateNamedPipe("\\\\.\\Pipe\\Jerry",  
                                           PIPE_ACCESS_DUPLEX, //open mode  
                                           PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, //  pipe mode 
                                           1,//Num. of MaxInstances: between 1 and PIPE_UNLIMITED_INSTANCES  
                                           0, // out buffer size  
                                           0, // in buffer size  
                                           1000, //timeout  
                                           NULL //Security descriptor  
             )) == INVALID_HANDLE_VALUE)  
        {  
            printf("CreateNamedPipe failed with error %d\n",  
                GetLastError());  
            return 0;  
        }  
      
        printf("Server is now running\n");  
      
        if (ConnectNamedPipe(PipeHandle, NULL) == 0)  
        {  
            printf("ConnectNamedPipe failed with error %d\n", GetLastError());  
            CloseHandle(PipeHandle);  
            return 0;  
        }  
      
        if (ReadFile(PipeHandle, buffer, sizeof(buffer), &BytesRead,  NULL) <= 0)  
        {  
            printf("ReadFile failed with error %d\n", GetLastError());  
            CloseHandle(PipeHandle);  
            return 0;  
        }  
      
        printf("%.*s\n", BytesRead, buffer);  
      
        if (DisconnectNamedPipe(PipeHandle) == 0)  
        {  
            printf("DisconnectNamedPipe failed with error %d\n",  
                GetLastError());  
            return 0;  
        }  
      
        CloseHandle(PipeHandle);  
        return 0;  
    }
    //客户程序
    #include <windows.h>  
    #include <stdio.h>  
      
    #define PIPE_NAME "\\\\.\\Pipe\\Jerry"  
      
    void main(void) {  
      
        HANDLE PipeHandle;  
        DWORD BytesWritten;  
      
        if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0)  
        {  
            printf("WaitNamedPipe failed with error %d\n",  
                GetLastError());  
            return;  
        }  
      
        // Open the named pipe file handle  
        if ((PipeHandle = CreateFile(PIPE_NAME,  
            GENERIC_READ | GENERIC_WRITE, 0,  
            (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,  
            FILE_ATTRIBUTE_NORMAL,  
            (HANDLE) NULL)) == INVALID_HANDLE_VALUE)  
        {  
            printf("CreateFile failed with error %d\n", GetLastError());  
            return;  
        }  
      
        if (WriteFile(PipeHandle, "This is a test", 14, &BytesWritten,   
            NULL) == 0)  
        {  
            printf("WriteFile failed with error %d\n", GetLastError());  
            CloseHandle(PipeHandle);  
            return;  
        }  
      
        printf("Wrote %d bytes", BytesWritten);  
      
        CloseHandle(PipeHandle);  
    }